[pypy-svn] r49982 - pypy/dist/pypy/lang/prolog/interpreter
cfbolz at codespeak.net
cfbolz at codespeak.net
Fri Dec 21 14:55:47 CET 2007
Author: cfbolz
Date: Fri Dec 21 14:55:46 2007
New Revision: 49982
Added:
pypy/dist/pypy/lang/prolog/interpreter/eclipseprologparser.py (contents, props changed)
pypy/dist/pypy/lang/prolog/interpreter/targetparserstandalone.py (contents, props changed)
Log:
some hacks to make a prolog parser that Jens can use to make a Prolog editor in
Eclipse. Extremely advanced technology.
Added: pypy/dist/pypy/lang/prolog/interpreter/eclipseprologparser.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/interpreter/eclipseprologparser.py Fri Dec 21 14:55:46 2007
@@ -0,0 +1,300 @@
+import autopath
+from pypy.lang.prolog.interpreter.parsing import OrderTransformer, make_default_operations, unescape
+from pypy.rlib.parsing.tree import Nonterminal, Symbol, RPythonVisitor
+
+class ASTTermBuilder(RPythonVisitor):
+
+ def __init__(self):
+ self.varname_to_var = {}
+
+ def build(self, s):
+ "NOT_RPYTHON"
+ if isinstance(s, list):
+ return self.build_many(s)
+ return self.build_query(s)
+
+ def build_many(self, trees):
+ ot = OrderTransformer()
+ facts = []
+ for tree in trees:
+ s = ot.transform(tree)
+ facts.append(self.build_fact(s))
+ return facts
+
+ def build_query(self, s):
+ ot = OrderTransformer()
+ s = ot.transform(s)
+ return self.visit(s.children[0])
+
+ def build_fact(self, node):
+ self.varname_to_var = {}
+ return self.visit(node.children[0])
+
+ def visit(self, node):
+ node = self.find_first_interesting(node)
+ return self.dispatch(node)
+
+ def general_nonterminal_visit(self, node):
+ children = []
+ name = ""
+ token = None
+ for child in node.children:
+ if isinstance(child, Symbol):
+ name = self.general_symbol_visit(child).name
+ token = self.make_token(child)
+ else:
+ children.append(child)
+ children = [self.visit(child) for child in children]
+ if len(children) == 1 and (name == "-" or name == "+"):
+ if name == "-":
+ factor = -1
+ else:
+ factor = 1
+ child = children[0]
+ if isinstance(child, Number):
+ child.value *= factor
+ return child
+ if isinstance(child, Float):
+ child.value *= factor
+ return child
+ result = Term()
+ result.setup(token, children, name)
+ return result
+
+ def build_list(self, node):
+ result = []
+ while node is not None:
+ node = self._build_list(node, result)
+ return result
+
+ def _build_list(self, node, result):
+ node = self.find_first_interesting(node)
+ if isinstance(node, Nonterminal):
+ child = node.children[1]
+ if (isinstance(child, Symbol) and
+ node.children[1].additional_info == ","):
+ element = self.visit(node.children[0])
+ result.append(element)
+ return node.children[2]
+ result.append(self.visit(node))
+
+ def find_first_interesting(self, node):
+ if isinstance(node, Nonterminal) and len(node.children) == 1:
+ return self.find_first_interesting(node.children[0])
+ return node
+
+ def general_symbol_visit(self, node):
+ if node.additional_info.startswith("'"):
+ end = len(node.additional_info) - 1
+ assert end >= 0
+ name = unescape(node.additional_info[1:end])
+ else:
+ name = node.additional_info
+ result = Atom()
+ result.setup(self.make_token(node), name)
+ return result
+
+ def visit_VAR(self, node):
+ varname = node.additional_info
+ result = Var()
+ result.setup(self.make_token(node), varname)
+ return result
+
+ def visit_NUMBER(self, node):
+ s = node.additional_info
+ try:
+ result = Number()
+ result.setup(self.make_token(node), int(s))
+ return result
+ except ValueError:
+ result = Float()
+ result.setup(self.make_token(node), float(s))
+ return result
+
+ def visit_complexterm(self, node):
+ name = self.general_symbol_visit(node.children[0]).name
+ children = self.build_list(node.children[2])
+ result = Term()
+ result.setup(self.make_token(node.children[1]), children, name)
+ return result
+
+ def visit_expr(self, node):
+ if node.children[0].additional_info == '-':
+ result = self.visit(node.children[1])
+ if isinstance(result, Number):
+ result.value = -result.value
+ elif isinstance(result, Float):
+ result.value = -result.value
+ return self.visit(node.children[1])
+
+ def visit_listexpr(self, node):
+ node = node.children[1]
+ if len(node.children) == 1:
+ l = self.build_list(node)
+ start = Atom()
+ start.setup(None, "[]")
+ else:
+ l = self.build_list(node.children[0])
+ start = self.visit(node.children[2])
+ l.reverse()
+ curr = start
+ for elt in l:
+ curr = Term()
+ curr.setup(None, [elt, curr], ".")
+ return curr
+
+ def make_token(self, node):
+ token = Token()
+ source_pos = node.token.source_pos
+ token.setup(node.token.source, source_pos.i, source_pos.lineno,
+ source_pos.columnno)
+ return token
+
+
+class Token(object):
+ def __init__(self):
+ pass
+
+ def setup(self, text, startpos, line, column):
+ self.text = text
+ self.startpos = startpos
+ self.line = line
+ self.column = column
+
+class Node(object):
+ def __init__(self):
+ self.children = [None] # trick the annotator
+
+ def setup(self, token, children=None):
+ self.token = token
+ if children is not None:
+ self.children = children
+ else:
+ self.children = []
+
+ def num_children(self):
+ return len(self.children)
+
+ def get_child(self, i):
+ return self.children[i]
+
+class Atom(Node):
+ def __init__(self):
+ pass
+ def setup(self, token, name):
+ Node.setup(self, token)
+ self.name = name
+
+class Number(Node):
+ def __init__(self):
+ pass
+ def setup(self, token, value):
+ Node.setup(self, token)
+ self.value = value
+
+class Float(Node):
+ def __init__(self):
+ pass
+ def setup(self, token, value):
+ Node.setup(self, token)
+ self.value = value
+
+class Var(Node):
+ def __init__(self):
+ pass
+ def setup(self, token, varname):
+ Node.setup(self, token)
+ self.varname = varname
+
+class Term(Node):
+ def __init__(self):
+ pass
+ def setup(self, token, children, name):
+ Node.setup(self, token, children)
+ self.name = name
+
+
+class Lines(object):
+ def __init__(self):
+ self.parser = None
+ self.operations = make_default_operations()
+ self.terms = []
+
+ def num_terms(self):
+ return len(self.terms)
+
+ def get_term(self, i):
+ return self.terms[i]
+
+class ParseError(Exception):
+ def __init__(self, pos, reason):
+ self.pos = pos
+ self.reason = reason
+ self.args = (pos, reason)
+
+
+def _build_and_run(lines, tree):
+ from pypy.lang.prolog.interpreter.parsing import TermBuilder
+ builder = ASTTermBuilder()
+ term = builder.build_query(tree)
+ if (isinstance(term, Term) and term.name == ":-" and
+ len(term.children) == 1):
+ child = term.get_child(0)
+ if isinstance(child, Term) and child.name == "op":
+ if len(child.children) != 3:
+ raise ParseError(child.token.startpos, "expecting three arguments")
+ precedence = child.children[0]
+ form = child.children[1]
+ name = child.children[2]
+ if not isinstance(precedence, Number):
+ raise ParseError(precedence.token.startpos, "first argument to op should be number")
+ if not isinstance(form, Atom):
+ raise ParseError(precedence.token.startpos, "second argument to op should be atom")
+ if not isinstance(name, Atom):
+ raise ParseError(precedence.token.startpos, "third argument to op should be atom")
+ parser = impl_op(lines.operations, precedence.value, form.name, name.name)
+ lines.parser = parser
+
+ lines.terms.append(term)
+ return lines.parser
+
+def parse(s):
+ from pypy.lang.prolog.interpreter.parsing import parse_file
+ lines = Lines()
+ trees = parse_file(s, lines.parser, _build_and_run, lines)
+ return lines
+
+
+def impl_op(operations, precedence, typ, name):
+ from pypy.lang.prolog.interpreter import parsing
+ precedence_to_ops = {}
+ for prec, allops in operations:
+ precedence_to_ops[prec] = allops
+ for form, ops in allops:
+ try:
+ index = ops.index(name)
+ del ops[index]
+ except ValueError:
+ pass
+ if precedence != 0:
+ if precedence in precedence_to_ops:
+ allops = precedence_to_ops[precedence]
+ for form, ops in allops:
+ if form == typ:
+ ops.append(name)
+ break
+ else:
+ allops.append((typ, [name]))
+ else:
+ for i in range(len(operations)):
+ (prec, allops) = operations[i]
+ if precedence > prec:
+ operations.insert(i, (precedence, [(typ, [name])]))
+ break
+ else:
+ operations.append((precedence, [(typ, [name])]))
+ return parsing.make_parser_at_runtime(operations)
+
+
+if __name__ == '__main__':
+ x = parse(":- op(900, xfx, hello). a hello b.")
Added: pypy/dist/pypy/lang/prolog/interpreter/targetparserstandalone.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/prolog/interpreter/targetparserstandalone.py Fri Dec 21 14:55:46 2007
@@ -0,0 +1,10 @@
+from pypy.lang.prolog.interpreter.eclipseprologparser import parse
+
+def entry_point(args):
+ if len(args) > 1:
+ t = parse(args[1])
+ return 0
+ return -1
+
+def target(driver, args):
+ return entry_point, None
More information about the Pypy-commit
mailing list