For Lipl, I can parse a(b c, d, e)
and
a (b c, d, e)
differently. First is a function call
while the second one is 2 tokens: Atom and List.
a = 1 .
b = 2 .
f(a, b) = [a + b] .
print f(a, b) .
If I have that, first appearance of f(a, b)
should be
distinguished from the second appearance after print
.
I can mark the declaration like: @f(a, b)
. But, even
if I don't mark it as declaration, LiplMachine can look at the
namespace for function f. If f doesn't exist it can be considered
as a declaration. Or, I can always evaluate when a token is popped
from the stack, not when it is pushed to.
= f(a, b) [a + b] .
is fine too because when
f(a, b)
is popped from the queue, not the stack,
=
is actually popping it. So, LipleMachine will know
that f(a, b)
is a declaration, not function call.
import pyparsing as pp
import sys
pp.ParseExpression.setDefaultWhitespaceChars("")
WS = pp.Suppress(pp.White())
OptWS = pp.Suppress(pp.Optional(WS))
LParen = pp.Suppress('(' + OptWS)
RParen = pp.Suppress(OptWS + ')')
Comma = pp.Suppress(OptWS + ',' + OptWS)
Atom = pp.Word(pp.alphas + '_', pp.alphanums + '_')\
.setResultsName('Atom').setName('Atom')
Token = pp.Forward().setResultsName('Token')
Tokens = pp.Group(Token + pp.ZeroOrMore(WS + Token))\
.setResultsName('Tokens').setName('Tokens')
CommaTokens = (Tokens + pp.ZeroOrMore(Comma + Tokens))\
.setResultsName('CommaTokens').setName('CommaTokens')
List = pp.Group(LParen + CommaTokens + RParen)\
.setResultsName('List').setName('List')
Funcall = pp.Group(Atom + List)\
.setResultsName('Funcall').setName('Funcall')
Token << (List | Funcall | Atom)
S = (Tokens + pp.StringEnd())\
.setResultsName('S').setName('S').leaveWhitespace()#.setDebug()
def print_tree(results, tab=2, level=0):
"prints ParseResults"
if type(results) != pp.ParseResults: #terminal
print (' '*level) + '> ' + str(results)
return
print (' '*level) + '- ' + results.getName() + ':'
for x in results:
print_tree(x, tab, level+tab)
def process(x):
"parses and prints result"
try:
print x
result = S.parseString(x)
print ">>>", result
print_tree(result)
#result.dump()
print ">>> [PASS]"
except pp.ParseException, err:
print x
print (" " * (err.col - 1)) + "^"
print err
print ">>> [FAIL]"
def test(li):
for x in li:
process(x)
def main(argv=None):
if argv is None:
argv = sys.argv
test(["a b (_a0, fun(arg1, arg2), a b (f,g),i)"])
while True:
line = raw_input("* ")
if line == "q":
print "Bye."
sys.exit(0)
process(line)
if __name__ == "__main__":
main()
No comments:
Post a Comment