mirror of
https://github.com/lloeki/wasp.git
synced 2025-12-06 10:44:39 +01:00
quote + simpler recursive descent (less boxing)
This commit is contained in:
parent
12da94d927
commit
91020ddfe6
1 changed files with 47 additions and 31 deletions
78
parser.py
78
parser.py
|
|
@ -1,20 +1,23 @@
|
|||
from __future__ import print_function
|
||||
from pprint import pprint
|
||||
from rply import ParserGenerator, LexerGenerator
|
||||
from rply.token import BaseBox
|
||||
|
||||
lg = LexerGenerator()
|
||||
lg.add("LPAREN", r"\(")
|
||||
lg.add("RPAREN", r"\)")
|
||||
lg.add("QUOTE", r"'")
|
||||
lg.add("ATOM", r"[^\s()]+")
|
||||
lg.ignore(r"\s+")
|
||||
|
||||
pg = ParserGenerator(["LPAREN", "RPAREN", "ATOM"])
|
||||
pg = ParserGenerator(["QUOTE", "LPAREN", "RPAREN", "ATOM"])
|
||||
|
||||
|
||||
@pg.error
|
||||
def error_handler(token):
|
||||
raise ValueError("unexpected %s" % token.gettokentype())
|
||||
type = token.gettokentype()
|
||||
pos = token.getsourcepos()
|
||||
raise ValueError("unexpected %s at (%s, %s)" %
|
||||
(type, pos.lineno, pos.colno))
|
||||
|
||||
|
||||
@pg.production("main : sexpr")
|
||||
|
|
@ -22,49 +25,52 @@ def main(p):
|
|||
return p[0]
|
||||
|
||||
|
||||
@pg.production("sexpr : LPAREN expr RPAREN")
|
||||
@pg.production("sexpr : ATOM")
|
||||
@pg.production("sexpr : QUOTE sexpr")
|
||||
@pg.production("sexpr : LPAREN list RPAREN")
|
||||
def sexpr(p):
|
||||
return BoxSexpr(p[1])
|
||||
if p[0].gettokentype() == "ATOM":
|
||||
return BoxAtom(p[0].getstr())
|
||||
elif p[0].gettokentype() == "QUOTE":
|
||||
return BoxQuote(p[1])
|
||||
else:
|
||||
return p[1]
|
||||
|
||||
|
||||
@pg.production("expr : ATOM")
|
||||
def atom(p):
|
||||
return BoxAtom(p[0].getstr())
|
||||
|
||||
|
||||
@pg.production("expr : ATOM sexpr")
|
||||
@pg.production("expr : ATOM expr")
|
||||
def sexpr(p):
|
||||
return BoxExpr(BoxAtom(p[0].getstr()), p[1])
|
||||
@pg.production("list : sexpr")
|
||||
@pg.production("list : sexpr list")
|
||||
def list(p):
|
||||
if len(p) == 1:
|
||||
return BoxPair(p[0])
|
||||
else:
|
||||
return BoxPair(p[0], p[1])
|
||||
|
||||
lexer = lg.build()
|
||||
parser = pg.build()
|
||||
|
||||
|
||||
class BoxSexpr(BaseBox):
|
||||
def __init__(self, expr):
|
||||
self.expr = expr
|
||||
class BoxQuote(BaseBox):
|
||||
def __init__(self, sexpr):
|
||||
self.sexpr = sexpr
|
||||
|
||||
def expr(self):
|
||||
return self.expr
|
||||
def sexpr(self):
|
||||
return self.sexpr
|
||||
|
||||
def __str__(self):
|
||||
return "( %s )" % (self.expr)
|
||||
return "' %s" % self.sexpr
|
||||
|
||||
|
||||
class BoxExpr(BaseBox):
|
||||
def __init__(self, atom, expr):
|
||||
self.atom = atom
|
||||
self.expr = expr
|
||||
|
||||
def atom(self):
|
||||
return self.atom
|
||||
|
||||
def expr(self):
|
||||
return self.expr
|
||||
class BoxPair(BaseBox):
|
||||
def __init__(self, x, y=None):
|
||||
self.x = x
|
||||
self.y = y
|
||||
|
||||
def __str__(self):
|
||||
return "%s . ( %s )" % (self.atom, self.expr)
|
||||
if self.y is None:
|
||||
y = "NIL"
|
||||
else:
|
||||
y = self.y
|
||||
return "(%s . %s)" % (self.x, y)
|
||||
|
||||
|
||||
class BoxAtom(BaseBox):
|
||||
|
|
@ -77,4 +83,14 @@ class BoxAtom(BaseBox):
|
|||
def __str__(self):
|
||||
return "%s" % (self.atom)
|
||||
|
||||
|
||||
print(parser.parse(lexer.lex("1")))
|
||||
print(parser.parse(lexer.lex("'1")))
|
||||
print(parser.parse(lexer.lex("+")))
|
||||
print(parser.parse(lexer.lex("'+")))
|
||||
print(parser.parse(lexer.lex("(+ 1 2)")))
|
||||
print(parser.parse(lexer.lex("'(+ 1 2)")))
|
||||
print(parser.parse(lexer.lex("(+ 1 (* 3 2))")))
|
||||
print(parser.parse(lexer.lex("'(+ 1 (* 3 2))")))
|
||||
print(parser.parse(lexer.lex("(+ (* 4 5) (* 3 2))")))
|
||||
print(parser.parse(lexer.lex("(+ '(* 4 5) (* 3 2))")))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue