Implemented interpreter, almost fully documented
This commit is contained in:
@@ -17,22 +17,52 @@ BOOLEAN_PRECEDENCE = [
|
||||
]
|
||||
|
||||
#Helper
|
||||
def precedence(value_parser, precedence_levels, combine):
|
||||
def op_parser(precedence_level):
|
||||
return any_op_in_list(precedence_level) ^ combine
|
||||
parser = value_parser * op_parser(precedence_levels[0])
|
||||
for precedence_level in precedence_levels[1:]:
|
||||
parser = parser * op_parser(precedence_level)
|
||||
def precedence(value_parser, precedences, combine):
|
||||
def op_parser(precedence):
|
||||
return any_op_in_list(precedence) ^ combine
|
||||
parser = value_parser * op_parser(precedences[0])
|
||||
for precedence in precedences[1:]:
|
||||
parser = parser * op_parser(precedence)
|
||||
return parser
|
||||
|
||||
def process_binop(op):
|
||||
"""
|
||||
Takes a binary operation as input and
|
||||
returns a function that build AST nodes
|
||||
given the operands.
|
||||
|
||||
op -- the operation
|
||||
|
||||
returns -- a function that takes two operands
|
||||
and returns a Binary Arithmetic AST
|
||||
node
|
||||
"""
|
||||
return lambda l, r: BinArithmeticExp(op, l, r)
|
||||
|
||||
def process_relop(parsed):
|
||||
""""
|
||||
Takes a parsed relational operation and returns
|
||||
an AST node.
|
||||
|
||||
parsed -- a tuple of the form ((left, operation), right)
|
||||
|
||||
returns -- an AST node representing the expression
|
||||
"""
|
||||
((left, op), right) = parsed
|
||||
return RelationExp(op, left, right)
|
||||
|
||||
def process_logic(op):
|
||||
"""
|
||||
Takes a logical operation and returns a function
|
||||
consuming two operands, building an AST node from them.
|
||||
|
||||
op -- the operation
|
||||
|
||||
returns -- a function that builds Logical Expression
|
||||
AST nodes
|
||||
|
||||
throws -- RuntimeError on unknown operator
|
||||
"""
|
||||
if op == 'and':
|
||||
return lambda l, r: AndExp(l, r)
|
||||
elif op == 'or':
|
||||
@@ -45,46 +75,105 @@ def process_group(parsed):
|
||||
return p
|
||||
|
||||
def any_op_in_list(ops):
|
||||
"""
|
||||
Builds a keyword parser from all given operations.
|
||||
|
||||
ops -- a list of operators
|
||||
|
||||
returns -- a parser matching all operators
|
||||
"""
|
||||
op_parsers = [keyword(op) for op in ops]
|
||||
parser = reduce(lambda l, r: l | r, op_parsers)
|
||||
return parser
|
||||
return reduce(lambda l, r: l | r, op_parsers)
|
||||
|
||||
#Parser
|
||||
num = Tag(INT) ^ (lambda i: int(i))
|
||||
imp_id = Tag(ID)
|
||||
|
||||
def keyword(kw):
|
||||
"""
|
||||
The keyword parser. Takes a keyword
|
||||
and returns a Reserved AST node.
|
||||
|
||||
kw -- the operation as string
|
||||
|
||||
returns -- a corresponding Reserved AST node
|
||||
"""
|
||||
return Reserved(kw, RESERVED)
|
||||
|
||||
def arithmetic_group():
|
||||
"""
|
||||
Matches groups of arithmetic operations.
|
||||
|
||||
returns -- a parser matching grouped arithmetic operations
|
||||
"""
|
||||
return keyword('(') + Lazy(arithmetic_exp) + keyword(')') ^ process_group
|
||||
|
||||
def arithmetic_value():
|
||||
"""
|
||||
Matches numbers and variables.
|
||||
|
||||
returns -- a parser matching all kinds of values
|
||||
"""
|
||||
return ((num ^ (lambda i: IntArithmeticExp(i))) |
|
||||
(id ^ (lambda v: VarArithmeticExp(v))))
|
||||
(imp_id ^ (lambda v: VarArithmeticExp(v))))
|
||||
|
||||
def arithmetic_term():
|
||||
"""
|
||||
Matches an arithmetic term.
|
||||
|
||||
returns -- a parser matching an arithmetic value or group
|
||||
"""
|
||||
return arithmetic_value() | arithmetic_group()
|
||||
|
||||
def arithmetic_exp():
|
||||
"""
|
||||
Matches arithmetic expressions, valuing precedence.
|
||||
|
||||
returns -- a parser correctly matching arithmetic expressions
|
||||
"""
|
||||
return precedence(arithmetic_term(),
|
||||
ARITHMETIC_PRECEDENCE,
|
||||
process_binop)
|
||||
|
||||
def boolean_not():
|
||||
"""
|
||||
Matches the boolean not with its arguments.
|
||||
|
||||
returns -- a parser matching the boolean not
|
||||
"""
|
||||
return keyword('not') + Lazy(boolean_term) ^ (lambda parsed: NotExp(parsed[1]))
|
||||
|
||||
def boolean_relop():
|
||||
"""
|
||||
Matches boolean relational operations.
|
||||
|
||||
returns -- a parser matching all relations
|
||||
"""
|
||||
relops = ['<', '<=', '>', '>=', '=', '!=']
|
||||
return arithmetic_exp() + any_op_in_list(relops) + arithmetic_exp() ^ process_relop
|
||||
|
||||
def boolean_group():
|
||||
"""
|
||||
Matches grouped boolean expressions
|
||||
|
||||
returns -- a parser matching groups of boolean expressions
|
||||
"""
|
||||
return keyword('(') + Lazy(boolean_exp) + keyword(')') ^ process_group
|
||||
|
||||
def boolean_term():
|
||||
"""
|
||||
Matches boolean terms.
|
||||
|
||||
returns -- a parser matching boolean terms
|
||||
"""
|
||||
return boolean_not() | boolean_relop() | boolean_group()
|
||||
|
||||
def boolean_exp():
|
||||
"""
|
||||
Matches boolean expressing, valuing precedence.
|
||||
|
||||
returns -- a parser correctly matching arithmetic expressions
|
||||
"""
|
||||
return precedence(boolean_term(),
|
||||
BOOLEAN_PRECEDENCE,
|
||||
process_logic)
|
||||
@@ -126,5 +215,5 @@ def statements():
|
||||
def parser():
|
||||
return Phrase(statements())
|
||||
|
||||
def imp_parser(tokens):
|
||||
def parse(tokens):
|
||||
return parser()(tokens, 0)
|
||||
|
Reference in New Issue
Block a user