Create simple calc as test draft

This commit is contained in:
Bartłomiej Pluta
2019-07-10 20:14:05 +02:00
parent 76eabbff0e
commit aefa8e8f3c
5 changed files with 111 additions and 9 deletions

View File

@@ -93,22 +93,50 @@ class Parser:
# leftAssociative -> left | left OP right
@staticmethod
def leftAssociativeOperatorParser(leftParser, operatorTokenType, rightParser, createNode):
def leftAssociativeOperatorParser(leftParser, operatorTokenTypes, rightParser, createNode):
from smnp.ast.node.operator import OperatorNode
def parse(input):
operatorParser = Parser.oneOfTerminals(*operatorTokenTypes, createNode=lambda val, pos: OperatorNode.withChildren([val], pos))
left = leftParser(input)
if left.result:
operator = Parser.terminalParser(operatorTokenType, lambda val, pos: OperatorNode.withChildren([val], pos))(input)
operator = operatorParser(input)
while operator.result:
right = rightParser(input)
left = ParseResult.OK(createNode(left.node, operator.node, right.node))
operator = Parser.terminalParser(operatorTokenType, lambda val, pos: OperatorNode.withChildren([val], pos))(input)
operator = operatorParser(input)
return left
return ParseResult.FAIL()
return parse
@staticmethod
def oneOfTerminals(*tokenTypes, createNode=None):
return Parser.oneOf(*[ Parser.terminalParser(expectedType, createNode=createNode) for expectedType in tokenTypes ])
# leftAssociative -> left OP right | right
@staticmethod
def leftAssociativeOperatorOrRightParser(leftParser, operatorTokenType, rightParser, createNode):
from smnp.ast.node.operator import OperatorNode
def parse(input):
left = leftParser(input)
oneAtLeast = False
if left.result:
operator = Parser.terminalParser(operatorTokenType, lambda val, pos: OperatorNode.withChildren([val], pos))(input)
while operator.result:
oneAtLeast = True
right = rightParser(input)
left = ParseResult.OK(createNode(left.node, operator.node, right.node))
operator = Parser.terminalParser(operatorTokenType, lambda val, pos: OperatorNode.withChildren([val], pos))(input)
if oneAtLeast:
return left
return ParseResult.FAIL()
return Parser.oneOf(parse, rightParser)
# loop -> start item* end
@staticmethod
def loop(startParser, itemParser, endParser, createNode):
@@ -154,6 +182,10 @@ class Parser:
return parse
@staticmethod
def epsilon():
return lambda *args: ParseResult.OK(NoneNode())
@staticmethod
def many(parser, createNode):
def parse(input):