Improve parser to contain name and subparsers
This commit is contained in:
@@ -10,6 +10,34 @@ def parse(input):
|
||||
|
||||
|
||||
class Parser:
|
||||
def __init__(self, parse, name=None, parsers=None):
|
||||
if parsers is None:
|
||||
parsers = []
|
||||
self.parsers = parsers
|
||||
|
||||
self._parse = parse
|
||||
if name is None:
|
||||
name = parse.__name__
|
||||
self.name = name
|
||||
|
||||
def parse(self, input):
|
||||
result = self._parse(input)
|
||||
if result is None:
|
||||
return ParseResult.FAIL()
|
||||
|
||||
if not isinstance(result, ParseResult):
|
||||
raise RuntimeError(f"_parse() method of '{self.__class__.__name__}' class haven't returned ParseResult object")
|
||||
|
||||
return result
|
||||
|
||||
def __call__(self, input):
|
||||
return self.parse(input)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
# a -> A
|
||||
@staticmethod
|
||||
@@ -30,11 +58,11 @@ class Parser:
|
||||
|
||||
return ParseResult.FAIL()
|
||||
|
||||
return parse
|
||||
return Parser(parse, expectedType.name.lower())
|
||||
|
||||
# oneOf -> a | b | c | ...
|
||||
@staticmethod
|
||||
def oneOf(*parsers, exception=None):
|
||||
def oneOf(*parsers, exception=None, name="or"):
|
||||
def combinedParser(input):
|
||||
snap = input.snapshot()
|
||||
for parser in parsers:
|
||||
@@ -52,11 +80,11 @@ class Parser:
|
||||
input.reset(snap)
|
||||
return ParseResult.FAIL()
|
||||
|
||||
return combinedParser
|
||||
return Parser(combinedParser, name=name, parsers=parsers)
|
||||
|
||||
# allOf -> a b c ...
|
||||
@staticmethod
|
||||
def allOf(*parsers, createNode, exception=None):
|
||||
def allOf(*parsers, createNode, exception=None, name="all"):
|
||||
if len(parsers) == 0:
|
||||
raise RuntimeError("Pass one parser at least")
|
||||
|
||||
@@ -88,12 +116,12 @@ class Parser:
|
||||
|
||||
|
||||
|
||||
return extendedParser
|
||||
return Parser(extendedParser, name=name, parsers=parsers)
|
||||
|
||||
|
||||
# leftAssociative -> left | left OP right
|
||||
@staticmethod
|
||||
def leftAssociativeOperatorParser(leftParser, operatorTokenTypes, rightParser, createNode):
|
||||
def leftAssociativeOperatorParser(leftParser, operatorTokenTypes, rightParser, createNode, name="leftAssoc"):
|
||||
from smnp.ast.node.operator import OperatorNode
|
||||
|
||||
def parse(input):
|
||||
@@ -109,37 +137,15 @@ class Parser:
|
||||
|
||||
return ParseResult.FAIL()
|
||||
|
||||
return parse
|
||||
return Parser(parse, name=name, parsers=[leftParser, '|'.join([t.value for t in operatorTokenTypes]), rightParser])
|
||||
|
||||
@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)
|
||||
return Parser.oneOf(*[ Parser.terminalParser(expectedType, createNode=createNode) for expectedType in tokenTypes ], name='|'.join([t.value for t in tokenTypes]))
|
||||
|
||||
# loop -> start item* end
|
||||
@staticmethod
|
||||
def loop(startParser, itemParser, endParser, createNode):
|
||||
def loop(startParser, itemParser, endParser, createNode, name="loop"):
|
||||
def parse(input):
|
||||
items = []
|
||||
start = startParser(input)
|
||||
@@ -155,10 +161,10 @@ class Parser:
|
||||
|
||||
return ParseResult.FAIL()
|
||||
|
||||
return parse
|
||||
return Parser(parse, name, parsers=[startParser, itemParser, endParser])
|
||||
|
||||
@staticmethod
|
||||
def doAssert(parser, expected):
|
||||
def doAssert(parser, expected, name="!!"):
|
||||
def parse(input):
|
||||
result = parser(input)
|
||||
|
||||
@@ -169,10 +175,10 @@ class Parser:
|
||||
|
||||
return result
|
||||
|
||||
return parse
|
||||
return Parser(parse, name, parsers=parser)
|
||||
|
||||
@staticmethod
|
||||
def optional(parser):
|
||||
def optional(parser, name="??"):
|
||||
def parse(input):
|
||||
result = parser(input)
|
||||
if result.result:
|
||||
@@ -180,14 +186,14 @@ class Parser:
|
||||
|
||||
return ParseResult.OK(NoneNode())
|
||||
|
||||
return parse
|
||||
return Parser(parse, name, parsers=[parser])
|
||||
|
||||
@staticmethod
|
||||
def epsilon():
|
||||
return lambda *args: ParseResult.OK(NoneNode())
|
||||
|
||||
@staticmethod
|
||||
def many(parser, createNode):
|
||||
def many(parser, createNode, name="*"):
|
||||
def parse(input):
|
||||
results = []
|
||||
snap = input.snapshot()
|
||||
@@ -201,4 +207,4 @@ class Parser:
|
||||
input.reset(snap)
|
||||
return ParseResult.OK(createNode(results, pos) if len(results) > 0 else NoneNode())
|
||||
|
||||
return parse
|
||||
return Parser(parse, name, parsers=[parser])
|
||||
|
||||
Reference in New Issue
Block a user