mirror of
https://github.com/lloeki/wasp.git
synced 2025-12-06 10:44:39 +01:00
rply parser + historical implementation
This commit is contained in:
parent
93796389e0
commit
12da94d927
4 changed files with 169 additions and 0 deletions
13
factorial.py
Normal file
13
factorial.py
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
from lysssp import _eval, globs
|
||||||
|
|
||||||
|
_eval(['setq', 'factorial', ['lambda', ['x'],
|
||||||
|
['cond', [
|
||||||
|
[ ['equal?', 'x', 0], 1 ],
|
||||||
|
[ True, [ '*', 'x', ['factorial', ['-', 'x', 1]]]]]]]], globs)
|
||||||
|
|
||||||
|
def test():
|
||||||
|
print _eval(['factorial', 10], globs)
|
||||||
|
|
||||||
|
import timeit
|
||||||
|
|
||||||
|
print timeit.Timer(test).timeit(1)
|
||||||
3
lambda.py
Normal file
3
lambda.py
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
from lysssp import _eval, globs
|
||||||
|
|
||||||
|
print _eval(["apply", ["quote", ["lambda", [], 10]], ["quote", [20]]], globs)
|
||||||
73
lysssp.py
Executable file
73
lysssp.py
Executable file
|
|
@ -0,0 +1,73 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import inspect
|
||||||
|
import re
|
||||||
|
|
||||||
|
globs = {}
|
||||||
|
|
||||||
|
def isprim(name):
|
||||||
|
return inspect.isfunction(globs.get(name, None))
|
||||||
|
|
||||||
|
def islazy(name):
|
||||||
|
if isprim(name): return name in ['cond', 'quote', 'setq']
|
||||||
|
return globs.get(name, [None])[0] == 'macro'
|
||||||
|
|
||||||
|
def isatom(name):
|
||||||
|
return not (type(name) == list or type(name) == dict)
|
||||||
|
|
||||||
|
def setq(sexpr, context):
|
||||||
|
globs[sexpr[0]] = sexpr[1]
|
||||||
|
return sexpr[1]
|
||||||
|
|
||||||
|
def _apply(fn, args, context):
|
||||||
|
if isprim(fn): return globs[fn](args, context)
|
||||||
|
context = dict(zip(globs[fn][1], args))
|
||||||
|
return _eval(globs[fn][2], context)
|
||||||
|
|
||||||
|
def _eval(sexpr, context):
|
||||||
|
if isatom(sexpr):
|
||||||
|
if sexpr in context:
|
||||||
|
return context[sexpr]
|
||||||
|
return sexpr
|
||||||
|
|
||||||
|
fn = sexpr[0]
|
||||||
|
args = sexpr[1:]
|
||||||
|
|
||||||
|
if not islazy(fn):
|
||||||
|
args = map(lambda n: _eval(n, context), args)
|
||||||
|
return _apply(fn, args, context)
|
||||||
|
|
||||||
|
def _cond(sexpr, context):
|
||||||
|
for elem in sexpr[0]:
|
||||||
|
if _eval(elem[0], context): return _eval(elem[1], context)
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _read(sexpr):
|
||||||
|
grammar = r"(\()|(\))|([^()\s]+)|(\s+)"
|
||||||
|
|
||||||
|
def sequenceBuilder(match):
|
||||||
|
leftbracket, rightbracket, atom, whitespace = match.groups()
|
||||||
|
if(leftbracket): return '['
|
||||||
|
elif(rightbracket): return ']'
|
||||||
|
elif(atom): return '"' + atom + '"'
|
||||||
|
elif(whitespace): return ','
|
||||||
|
return eval(re.sub(grammar, sequenceBuilder, sexpr), None, None)
|
||||||
|
|
||||||
|
globs['setq'] = setq
|
||||||
|
globs['cond'] = _cond
|
||||||
|
globs['car'] = lambda sexpr, context: sexpr[0][0]
|
||||||
|
globs['cdr'] = lambda sexpr, context: sexpr[0][1:]
|
||||||
|
globs['quote'] = lambda sexpr, context: sexpr[0]
|
||||||
|
globs["apply"] = lambda sexpr, context: _apply(sexpr[0], sexpr[1], context)
|
||||||
|
globs['+'] = lambda sexpr, context: sexpr[0] + sexpr[1]
|
||||||
|
globs['-'] = lambda sexpr, context: sexpr[0] - sexpr[1]
|
||||||
|
globs['*'] = lambda sexpr, context: sexpr[0] * sexpr[1]
|
||||||
|
globs['/'] = lambda sexpr, context: sexpr[0] / sexpr[1]
|
||||||
|
globs['equal?'] = lambda sexpr, context: sexpr[0] == sexpr[1]
|
||||||
|
|
||||||
|
# FIXME: apply, eval the first arg
|
||||||
|
# TODO: define lambda func
|
||||||
|
# FIXME: sexpr=>lstruct
|
||||||
|
# TODO: _read, sexpr=>lstruct
|
||||||
|
# TODO: REPL while 1: print _eval(_read())
|
||||||
|
|
||||||
80
parser.py
Normal file
80
parser.py
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
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("ATOM", r"[^\s()]+")
|
||||||
|
lg.ignore(r"\s+")
|
||||||
|
|
||||||
|
pg = ParserGenerator(["LPAREN", "RPAREN", "ATOM"])
|
||||||
|
|
||||||
|
|
||||||
|
@pg.error
|
||||||
|
def error_handler(token):
|
||||||
|
raise ValueError("unexpected %s" % token.gettokentype())
|
||||||
|
|
||||||
|
|
||||||
|
@pg.production("main : sexpr")
|
||||||
|
def main(p):
|
||||||
|
return p[0]
|
||||||
|
|
||||||
|
|
||||||
|
@pg.production("sexpr : LPAREN expr RPAREN")
|
||||||
|
def sexpr(p):
|
||||||
|
return BoxSexpr(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])
|
||||||
|
|
||||||
|
lexer = lg.build()
|
||||||
|
parser = pg.build()
|
||||||
|
|
||||||
|
|
||||||
|
class BoxSexpr(BaseBox):
|
||||||
|
def __init__(self, expr):
|
||||||
|
self.expr = expr
|
||||||
|
|
||||||
|
def expr(self):
|
||||||
|
return self.expr
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "( %s )" % (self.expr)
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "%s . ( %s )" % (self.atom, self.expr)
|
||||||
|
|
||||||
|
|
||||||
|
class BoxAtom(BaseBox):
|
||||||
|
def __init__(self, atom):
|
||||||
|
self.atom = atom
|
||||||
|
|
||||||
|
def atom(self):
|
||||||
|
return self.atom
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "%s" % (self.atom)
|
||||||
|
|
||||||
|
print(parser.parse(lexer.lex("(+ 1 (* 3 2))")))
|
||||||
Loading…
Add table
Add a link
Reference in a new issue