Create almost working proof of concept with new parsers

This commit is contained in:
Bartłomiej Pluta
2019-07-11 19:10:13 +02:00
parent ed2c8dc6dd
commit e7674a4834
8 changed files with 128 additions and 103 deletions

View File

@@ -1,6 +1,7 @@
from smnp.ast.node.model import Node
from smnp.ast.parser import Parser
from smnp.ast.parser import Parsers
from smnp.token.type import TokenType
from smnp.util.singleton import SingletonParser
class Atom(Node):
@@ -43,52 +44,60 @@ class TypeLiteral(Atom):
pass
def IntegerParser(input):
return Parser.oneOf(
Parser.terminalParser(TokenType.INTEGER, lambda val, pos: IntegerLiteral.withValue(int(val), pos)),
Parser.allOf(
Parser.terminalParser(TokenType.MINUS),
Parser.terminalParser(TokenType.INTEGER, lambda val, pos: IntegerLiteral.withValue(int(val), pos)),
@SingletonParser
def IntegerParser():
return Parsers.oneOf(
Parsers.terminal(TokenType.INTEGER, lambda val, pos: IntegerLiteral.withValue(int(val), pos)),
Parsers.allOf(
Parsers.terminal(TokenType.MINUS),
Parsers.terminal(TokenType.INTEGER, lambda val, pos: IntegerLiteral.withValue(int(val), pos)),
createNode=lambda minus, integer: IntegerLiteral.withValue(-integer.value, minus.pos),
name="negative integer"
)
)(input)
name="negativeInteger"
),
name="int"
)
def StringParser(input):
return Parser.terminalParser(TokenType.STRING, createNode=StringLiteral.withValue)(input)
@SingletonParser
def StringParser():
return Parsers.terminal(TokenType.STRING, createNode=StringLiteral.withValue)
def NoteParser(input):
return Parser.terminalParser(TokenType.NOTE, createNode=NoteLiteral.withValue)(input)
@SingletonParser
def NoteParser():
return Parsers.terminal(TokenType.NOTE, createNode=NoteLiteral.withValue)
def BoolParser(input):
return Parser.terminalParser(TokenType.BOOL, createNode=BoolLiteral.withValue)(input)
@SingletonParser
def BoolParser():
return Parsers.terminal(TokenType.BOOL, createNode=BoolLiteral.withValue)
def TypeParser(input):
return Parser.terminalParser(TokenType.TYPE, createNode=TypeLiteral.withValue)(input)
@SingletonParser
def TypeParser():
return Parsers.terminal(TokenType.TYPE, createNode=TypeLiteral.withValue)
def LiteralParser(input):
return Parser.oneOf(
IntegerParser,
StringParser,
NoteParser,
BoolParser,
TypeParser,
@SingletonParser
def LiteralParser():
return Parsers.oneOf(
IntegerParser(),
StringParser(),
NoteParser(),
BoolParser(),
TypeParser(),
name="literal"
)(input)
)
def AtomParser(input):
@SingletonParser
def AtomParser():
from smnp.ast.node.identifier import IdentifierParser
return Parser.oneOf(
LiteralParser,
IdentifierParser,
return Parsers.oneOf(
LiteralParser(),
IdentifierParser(),
name="atom"
)(input)
)

View File

@@ -1,21 +1,31 @@
from smnp.ast.node.atom import AtomParser
from smnp.ast.node.list import ListParser
from smnp.ast.node.map import MapParser
from smnp.ast.node.operator import BinaryOperator
from smnp.ast.node.valuable import Valuable
from smnp.ast.parser import Parser
from smnp.ast.parser import Parsers
from smnp.token.type import TokenType
from smnp.util.singleton import SingletonParser
class Chain(Valuable):
pass
itemParser = Parser.oneOf(
ListParser,
MapParser,
AtomParser,
)
ChainParser = Parser.leftAssociativeOperatorParser(itemParser, [TokenType.DOT], itemParser,
lambda left, op, right: Chain.withValue(BinaryOperator.withValues(left, op, right)))
@SingletonParser
def ChainParser():
from smnp.ast.node.atom import AtomParser
itemParser = Parsers.oneOf(
#ListParser,
#MapParser,
AtomParser,
name="chainItem"
)
return Parsers.leftAssociativeOperatorParser(
itemParser,
[TokenType.DOT],
itemParser,
lambda left, op, right: Chain.withValue(BinaryOperator.withValues(left, op, right)),
name="chain"
)

View File

@@ -1,11 +1,10 @@
from smnp.ast.node.atom import Atom
from smnp.ast.node.expression import MaxPrecedenceExpressionParser
from smnp.ast.node.iterable import abstractIterableParser
from smnp.ast.node.model import Node
from smnp.ast.node.none import NoneNode
from smnp.ast.node.operator import BinaryOperator, Operator
from smnp.ast.parser import Parser
from smnp.ast.parser import Parsers
from smnp.token.type import TokenType
from smnp.util.singleton import SingletonParser
class Identifier(Atom):
@@ -49,24 +48,28 @@ class Assignment(BinaryOperator):
pass
def IdentifierParser(input):
identifierLiteralParser = Parser.terminalParser(TokenType.IDENTIFIER, createNode=Identifier.withValue)
@SingletonParser
def IdentifierParser():
identifierLiteralParser = Parsers.terminal(TokenType.IDENTIFIER, createNode=Identifier.withValue)
functionCallParser = Parser.allOf(
functionCallParser = Parsers.allOf(
identifierLiteralParser,
abstractIterableParser(ArgumentsList, TokenType.OPEN_PAREN, TokenType.CLOSE_PAREN, MaxPrecedenceExpressionParser),
createNode=lambda name, arguments: FunctionCall.withChildren(name, arguments)
#abstractIterableParser(ArgumentsList, TokenType.OPEN_PAREN, TokenType.CLOSE_PAREN, MaxPrecedenceExpressionParser),
createNode=lambda name, arguments: FunctionCall.withChildren(name, arguments),
name="functionCall"
)
assignmentParser = Parser.allOf(
assignmentParser = Parsers.allOf(
identifierLiteralParser,
Parser.terminalParser(TokenType.ASSIGN, createNode=Operator.withValue),
MaxPrecedenceExpressionParser,
createNode=lambda identifier, assign, expr: Assignment.withValues(identifier, assign, expr)
Parsers.terminal(TokenType.ASSIGN, createNode=Operator.withValue),
#MaxPrecedenceExpressionParser,
createNode=lambda identifier, assign, expr: Assignment.withValues(identifier, assign, expr),
name="assignment"
)
return Parser.oneOf(
return Parsers.oneOf(
assignmentParser,
functionCallParser,
identifierLiteralParser
)(input)
identifierLiteralParser,
name="idExpr"
)

View File

@@ -1,11 +1,11 @@
from smnp.ast.node.ignore import IgnoredNode
from smnp.ast.node.model import Node, ParseResult
from smnp.ast.node.none import NoneNode
from smnp.ast.parser import Parser
from smnp.ast.parser import Parsers
from smnp.token.type import TokenType
def abstractIterableParser(iterableNodeType, openTokenType, closeTokenType, itemParser):
def abstractIterableParser(iterableNodeType, openTokenType, closeTokenType, itemParser, name):
class AbstractIterable(Node):
def __init__(self, pos):
@@ -32,9 +32,10 @@ def abstractIterableParser(iterableNodeType, openTokenType, closeTokenType, item
pass
def abstractIterableParser(input):
return Parser.oneOf(
return Parsers.oneOf(
emptyIterable,
openIterable
openIterable,
name=name
)(input)
def emptyIterable(input):
@@ -44,10 +45,11 @@ def abstractIterableParser(iterableNodeType, openTokenType, closeTokenType, item
node.next = close
return node
return Parser.allOf(
Parser.terminalParser(openTokenType),
Parser.terminalParser(closeTokenType),
createNode=createNode
return Parsers.allOf(
Parsers.terminal(openTokenType),
Parsers.terminal(closeTokenType),
createNode=createNode,
name=name+"Empty"
)(input)
def openIterable(input):
@@ -57,17 +59,19 @@ def abstractIterableParser(iterableNodeType, openTokenType, closeTokenType, item
node.next = tail
return node
return Parser.allOf(
Parser.terminalParser(openTokenType),
return Parsers.allOf(
Parsers.terminal(openTokenType),
itemParser,
abstractIterableTailParser,
createNode=createNode
createNode=createNode,
name=name+"Open"
)(input)
def abstractIterableTailParser(input):
return Parser.oneOf(
return Parsers.oneOf(
closeIterable,
nextItem,
name=name+"Tail"
)(input)
def nextItem(input):
@@ -77,15 +81,16 @@ def abstractIterableParser(iterableNodeType, openTokenType, closeTokenType, item
node.next = tail
return node
return Parser.allOf(
Parser.terminalParser(TokenType.COMMA, doAssert=True),
return Parsers.allOf(
Parsers.terminal(TokenType.COMMA, doAssert=True),
itemParser,
abstractIterableTailParser,
name=name+"NextItem",
createNode=createNode
)(input)
def closeIterable(input):
return Parser.terminalParser(closeTokenType)(input)
return Parsers.terminal(closeTokenType)(input)
return toFlatDesiredNode(iterableNodeType, abstractIterableParser)
@@ -105,7 +110,7 @@ def toFlatDesiredNode(iterableNodeType, parser):
return ParseResult.FAIL()
return Parser(parse, "flat", [parser])
#return Parser(parse, "flat", [parser])
def flattenList(node, output=None):

View File

@@ -1,8 +1,7 @@
from smnp.ast.node.atom import LiteralParser
from smnp.ast.node.iterable import abstractIterableParser
from smnp.ast.node.model import Node
from smnp.ast.node.operator import BinaryOperator, Operator
from smnp.ast.parser import Parser
from smnp.ast.parser import Parsers
from smnp.token.type import TokenType
@@ -30,17 +29,19 @@ class Map(Node):
def MapParser(input):
from smnp.ast.node.expression import MaxPrecedenceExpressionParser
from smnp.ast.node.atom import LiteralParser
#from smnp.ast.node.expression import MaxPrecedenceExpressionParser
keyParser = LiteralParser
valueParser = MaxPrecedenceExpressionParser
#valueParser = MaxPrecedenceExpressionParser
mapEntryParser = Parser.allOf(
mapEntryParser = Parsers.allOf(
keyParser,
Parser.terminalParser(TokenType.ARROW, createNode=Operator.withValue),
valueParser,
createNode=MapEntry.withValues
Parsers.terminal(TokenType.ARROW, createNode=Operator.withValue),
#valueParser,
createNode=MapEntry.withValues,
name="mapEntry"
)
mapParser = abstractIterableParser(Map, TokenType.OPEN_CURLY, TokenType.CLOSE_CURLY, mapEntryParser)
return abstractIterableParser(Map, TokenType.OPEN_CURLY, TokenType.CLOSE_CURLY, mapEntryParser)
return Parser(mapParser, "map", [mapParser])(input)

View File

@@ -1,8 +1,7 @@
from smnp.ast.node.atom import AtomParser
from smnp.ast.node.model import Node
from smnp.ast.parser import TerminalParser, OneOfParser, AllOfParser, OptionalParser, LoopParser
from smnp.error.base import SmnpException
from smnp.token.tokenizer import tokenize
from smnp.token.type import TokenType
def main():
@@ -16,24 +15,8 @@ def main():
super().__init__((-1, -1))
self.children = children
tokens = tokenize(['{*1^*1^}'])
parser = LoopParser(
TerminalParser(TokenType.OPEN_CURLY),
AllOfParser(
OneOfParser(
TerminalParser(TokenType.ASSIGN),
TerminalParser(TokenType.ASTERISK),
name="assignOrAsterisk"
),
OptionalParser(TerminalParser(TokenType.INTEGER), name="optInt"),
TerminalParser(TokenType.DASH),
name="aoaInt",
createNode=lambda a, b, c: TestNode([a, b, c])
),
TerminalParser(TokenType.CLOSE_CURLY),
createNode=lambda a, b, c: TestNode([a, b, c]),
name="block",
)
tokens = tokenize(['"fsfsvd" "Fsefs"'])
parser = AtomParser()
print(parser.grammar())
res = parser.parse(tokens)

0
smnp/util/__init__.py Normal file
View File

14
smnp/util/singleton.py Normal file
View File

@@ -0,0 +1,14 @@
from smnp.ast.parser import Parser
def SingletonParser(function):
def wrapper(*args, **kwargs):
if not hasattr(function, 'instance'):
function.instance = function(*args, **kwargs)
if not isinstance(function.instance, Parser):
raise RuntimeError(f"Function {function.__name__} haven't returned Parser object")
return function.instance
return wrapper