4 Commits

Author SHA1 Message Date
Bartłomiej Pluta
49e4c4487e --wip-- [skip ci] 2019-07-11 19:36:25 +02:00
Bartłomiej Pluta
e7674a4834 Create almost working proof of concept with new parsers 2019-07-11 19:10:13 +02:00
Bartłomiej Pluta
ed2c8dc6dd Create base for future parsers 2019-07-11 18:24:05 +02:00
Bartłomiej Pluta
f91e2a75de Create oneOf and allOf parsers 2019-07-11 17:23:39 +02:00
10 changed files with 409 additions and 268 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,32 @@
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, DecoratorParser
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):
@@ -31,70 +31,74 @@ def abstractIterableParser(iterableNodeType, openTokenType, closeTokenType, item
class AbstractIterableTail(AbstractIterable):
pass
def abstractIterableParser(input):
return Parser.oneOf(
emptyIterable,
openIterable
)(input)
def abstractIterableParser():
return Parsers.oneOf(
emptyIterable(),
openIterable(),
name=name
)
def emptyIterable(input):
def emptyIterable():
def createNode(open, close):
node = AbstractIterable(open.pos)
node.value = open
node.next = close
return node
return Parser.allOf(
Parser.terminalParser(openTokenType),
Parser.terminalParser(closeTokenType),
createNode=createNode
)(input)
return Parsers.allOf(
Parsers.terminal(openTokenType),
Parsers.terminal(closeTokenType),
createNode=createNode,
name=name+"Empty"
)
def openIterable(input):
def openIterable():
def createNode(open, item, tail):
node = AbstractIterable(open.pos)
node.value = item
node.next = tail
return node
return Parser.allOf(
Parser.terminalParser(openTokenType),
return Parsers.allOf(
Parsers.terminal(openTokenType),
itemParser,
abstractIterableTailParser,
createNode=createNode
)(input)
abstractIterableTailParser(),
createNode=createNode,
name=name+"Open"
)
def abstractIterableTailParser(input):
return Parser.oneOf(
closeIterable,
nextItem,
)(input)
def abstractIterableTailParser():
return Parsers.oneOf(
closeIterable(),
nextItem(),
name=name+"Tail"
)
def nextItem(input):
def nextItem():
def createNode(comma, item, tail):
node = AbstractIterableTail(item.pos)
node.value = 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,
abstractIterableTailParser(),
name=name+"NextItem",
createNode=createNode
)(input)
)
def closeIterable(input):
return Parser.terminalParser(closeTokenType)(input)
def closeIterable():
return Parsers.terminal(closeTokenType)
return toFlatDesiredNode(iterableNodeType, abstractIterableParser)
return abstractIterableParser()
#return toFlatDesiredNode(iterableNodeType, abstractIterableParser())
def toFlatDesiredNode(iterableNodeType, parser):
def parse(input):
result = parser(input)
def wrapper(result):
if result.result:
value = flattenList(result.node)
node = iterableNodeType(result.node.pos)
@@ -105,7 +109,7 @@ def toFlatDesiredNode(iterableNodeType, parser):
return ParseResult.FAIL()
return Parser(parse, "flat", [parser])
return DecoratorParser(wrapper, parser)
def flattenList(node, output=None):

View File

@@ -1,3 +1,4 @@
from smnp.ast.node.atom import AtomParser
from smnp.ast.node.iterable import abstractIterableParser
from smnp.ast.node.model import Node
from smnp.token.type import TokenType
@@ -7,7 +8,6 @@ class List(Node):
pass
def ListParser(input):
from smnp.ast.node.expression import MaxPrecedenceExpressionParser
return abstractIterableParser(List, TokenType.OPEN_SQUARE, TokenType.CLOSE_SQUARE,
MaxPrecedenceExpressionParser)(input)
def ListParser():
return abstractIterableParser(List, TokenType.OPEN_SQUARE, TokenType.CLOSE_SQUARE, AtomParser(), name="list")
#MaxPrecedenceExpressionParser)(input)

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

@@ -9,15 +9,8 @@ def parse(input):
return ProgramParser(input).node
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__
class Parser(object):
def __init__(self, name):
self.name = name
def parse(self, input):
@@ -26,10 +19,27 @@ class Parser:
return ParseResult.FAIL()
if not isinstance(result, ParseResult):
raise RuntimeError(f"_parse() method of '{self.__class__.__name__}' class haven't returned ParseResult object")
raise RuntimeError(
f"_parse() method of '{self.__class__.__name__}' class haven't returned ParseResult object")
return result
def _parse(self, input):
raise RuntimeError(f"_name method of '{self.__class__.__name__}' class is not implemented")
def grammar(self):
rules = []
self._grammarRules(rules)
return "\n".join(self._uniq(rules))
def _uniq(self, seq):
seen = set()
seen_add = seen.add
return [x for x in seq if not (x in seen or seen_add(x))]
def _grammarRules(self, output):
output.append(f"class '{self.__class__.__name__}' does not implement _grammarRules() method")
def __call__(self, input):
return self.parse(input)
@@ -39,171 +49,242 @@ class Parser:
def __repr__(self):
return self.__str__()
# a -> A
class Parsers:
@staticmethod
def terminalParser(expectedType, createNode=None, doAssert=False):
def provideNode(value, pos):
if createNode is None:
return IgnoredNode(pos)
return createNode(value, pos)
def terminal(expectedType, createNode=lambda val, pos: IgnoredNode(pos), doAssert=False):
return TerminalParser(expectedType, createNode, doAssert)
def parse(input):
if input.hasCurrent() and input.current().type == expectedType:
token = input.current()
input.ahead()
return ParseResult.OK(provideNode(token.value, token.pos))
elif doAssert:
found = f", found '{input.current().rawValue}'" if input.hasCurrent() else ""
raise SyntaxException(f"Expected '{expectedType.key}'{found}", input.currentPos())
return ParseResult.FAIL()
return Parser(parse, name=expectedType.name.lower())
# oneOf -> a | b | c | ...
@staticmethod
def oneOf(*parsers, exception=None, name="or"):
def combinedParser(input):
snap = input.snapshot()
for parser in parsers:
value = parser(input)
if value.result:
return value
def oneOf(*parsers, name, exception=None):
return OneOfParser(*parsers, name=name, exception=exception)
if exception is not None:
if callable(exception):
raise exception(input)
else:
raise exception
input.reset(snap)
return ParseResult.FAIL()
return Parser(combinedParser, name=name, parsers=parsers)
# allOf -> a b c ...
@staticmethod
def allOf(*parsers, createNode, exception=None, name="all"):
def allOf(*parsers, createNode, exception=None, name):
return AllOfParser(*parsers, createNode=createNode, exception=exception, name=name)
@staticmethod
def leftAssociativeOperatorParser(leftParser, operatorTokenTypes, rightParser, createNode, name):
return LeftAssociativeOperatorParser(leftParser, operatorTokenTypes, rightParser, createNode, name)
@staticmethod
def many(itemParser, createNode, name):
return ManyParser(itemParser, createNode, name)
@staticmethod
def optional(parser, name):
return OptionalParser(parser, name)
@staticmethod
def loop(startParser, itemParser, endParser, createNode, name):
return LoopParser(startParser, itemParser, endParser, createNode, name)
class DecoratorParser(Parser):
def __init__(self, wrapper, parser):
super().__init__(parser.name)
self.wrapper = wrapper
self.parser = parser
self._grammarRules = parser._grammarRules
def _parse(self, input):
result = self.parser.parse(input)
return self.wrapper(result)
class TerminalParser(Parser):
def __init__(self, expectedType, createNode=lambda val, pos: IgnoredNode(pos), doAssert=False):
super().__init__(expectedType.name.lower())
self.expectedType = expectedType
self.createNode = createNode
self.doAssert = doAssert
def _grammarRules(self, output):
output.append(f"{self.name} -> '{self.expectedType.value}'")
def _parse(self, input):
if input.isCurrent(self.expectedType):
token = input.current()
input.ahead()
return ParseResult.OK(self.createNode(token.value, token.pos))
elif self.doAssert:
found = f", found '{input.current().rawValue}'" if input.hasCurrent() else ""
raise SyntaxException(f"Expected '{self.expectedType.key}'{found}", input.currentPos())
return ParseResult.FAIL()
class OneOfParser(Parser):
def __init__(self, *parsers, name, exception=None):
super().__init__(name)
self.parsers = parsers
self.exception = exception
def _parse(self, input):
snap = input.snapshot()
for parser in self.parsers:
value = parser.parse(input)
if value.result:
return value
input.reset(snap) # TODO sprawdzic, czy koneiczne !!!!!
if self.exception is not None:
if callable(self.exception):
raise self.exception(input)
else:
raise self.exception
return ParseResult.FAIL()
def _grammarRules(self, output):
output.extend([ f"{self.name} -> {parser.name}" for parser in self.parsers ])
[ parser._grammarRules(output) for parser in self.parsers ]
class AllOfParser(Parser):
def __init__(self, *parsers, createNode, exception=None, name):
super().__init__(name)
if len(parsers) == 0:
raise RuntimeError("Pass one parser at least")
def extendedParser(input):
snap = input.snapshot()
self.parsers = parsers
self.createNode = createNode
self.exception = exception
results = []
def _parse(self, input):
snap = input.snapshot()
parsedItems = []
for parser in parsers:
result = parser(input)
if not result.result:
if exception is not None:
if callable(exception):
raise exception(input)
else:
raise exception
input.reset(snap)
return ParseResult.FAIL()
results.append(result.node)
node = createNode(*results)
if not isinstance(node, Node):
raise RuntimeError("Function 'createNode' haven't returned a Node object. Probably forget to pass 'return'")
return ParseResult.OK(node)
return Parser(extendedParser, name=name, parsers=parsers)
# leftAssociative -> left | left OP right
@staticmethod
def leftAssociativeOperatorParser(leftParser, operatorTokenTypes, rightParser, createNode, name="leftAssoc"):
from smnp.ast.node.operator import Operator
def parse(input):
operatorParser = Parser.oneOfTerminals(*operatorTokenTypes, createNode=lambda val, pos: Operator.withChildren([val], pos))
left = leftParser(input)
if left.result:
operator = operatorParser(input)
while operator.result:
right = rightParser(input)
left = ParseResult.OK(createNode(left.node, operator.node, right.node))
operator = operatorParser(input)
return left
return ParseResult.FAIL()
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 ], name='|'.join([t.value for t in tokenTypes]))
# loop -> start item* end
@staticmethod
def loop(startParser, itemParser, endParser, createNode, name="loop"):
def parse(input):
items = []
start = startParser(input)
if start.result:
while True:
end = endParser(input)
if end.result:
return ParseResult.OK(createNode(start.node, items, end.node))
item = itemParser(input)
if not item.result:
return ParseResult.FAIL()
items.append(item.node)
return ParseResult.FAIL()
return Parser(parse, name, parsers=[startParser, itemParser, endParser])
@staticmethod
def doAssert(parser, expected, name="!!"):
def parse(input):
result = parser(input)
for parser in self.parsers:
result = parser.parse(input)
if not result.result:
found = f", found '{input.current().rawValue}'" if input.hasCurrent() else ''
if self.exception is not None:
if callable(self.exception):
raise self.exception(input)
else:
raise self.exception
raise SyntaxException(f"Expected {expected}{found}", input.currentPos())
input.reset(snap)
return ParseResult.FAIL()
parsedItems.append(result.node)
node = self.createNode(*parsedItems)
if not isinstance(node, Node):
raise RuntimeError(f"Method 'createNode' of class '{self.__class__.__name__}' haven't returned a Node object. Probably forget to pass 'return'")
return ParseResult.OK(node)
def _grammarRules(self, output):
output.append(self.name + ' -> ' + ' '.join([ parser.name for parser in self.parsers ]))
[ parser._grammarRules(output) for parser in self.parsers ]
class LeftAssociativeOperatorParser(Parser):
def __init__(self, leftParser, operatorTokenTypes, rightParser, createNode, name):
from smnp.ast.node.operator import Operator
super().__init__(name)
self.leftParser = leftParser
self.rightParser = rightParser
self.createNode = createNode
self.operators = operatorTokenTypes
operatorParsers = [ TerminalParser(expectedType, createNode=lambda val, pos: Operator.withValue(val, pos)) for expectedType in operatorTokenTypes ]
self.operatorParser = OneOfParser(*operatorParsers, name="not important")
def _parse(self, input):
snap = input.snapshot()
left = self.leftParser.parse(input)
if left.result:
operator = self.operatorParser.parse(input)
while operator.result:
right = self.rightParser.parse(input)
left = ParseResult.OK(self.createNode(left.node, operator.node, right.node))
operator = self.operatorParser.parse(input)
return left
return ParseResult.FAIL()
def _grammarRules(self, output):
output.append('\n'.join([f"{self.name} -> {self.leftParser.name} {operator.name.lower()} {self.rightParser.name} | {self.leftParser.name}" for operator in self.operators]))
self.leftParser._grammarRules(output)
self.rightParser._grammarRules(output)
class ManyParser(Parser):
def __init__(self, itemParser, createNode, name):
super().__init__(name)
self.itemParser = itemParser
self.createNode = createNode
def _parse(self, input):
snap = input.snapshot()
parsedItems = []
pos = input.currentPos()
while True:
result = self.itemParser.parse(input)
if result.result:
parsedItems.append(result.node)
snap = input.snapshot()
else:
input.reset(snap)
return ParseResult.OK(self.createNode(parsedItems, pos) if len(parsedItems) > 0 else NoneNode())
def _grammarRules(self, output):
output.append(f"{self.name} -> {self.itemParser.name}*")
self.itemParser._grammarRules(output)
class OptionalParser(Parser):
def __init__(self, parser, name):
super().__init__(name)
self.parser = parser
def _parse(self, input):
result = self.parser.parse(input)
if result.result:
return result
return Parser(parse, name, parsers=parser)
return ParseResult.OK(NoneNode())
@staticmethod
def optional(parser, name="??"):
def parse(input):
result = parser(input)
if result.result:
return result
def _grammarRules(self, output):
output.append(f"{self.name} -> {self.parser.name}?")
return ParseResult.OK(NoneNode())
return Parser(parse, name, parsers=[parser])
class LoopParser(Parser):
def __init__(self, startParser, itemParser, endParser, createNode, name):
super().__init__(name)
self.startParser = startParser
self.itemParser = itemParser
self.endParser = endParser
self.createNode = createNode
@staticmethod
def epsilon():
return lambda *args: ParseResult.OK(NoneNode())
@staticmethod
def many(parser, createNode, name="*"):
def parse(input):
results = []
snap = input.snapshot()
pos = input.currentPos()
def _parse(self, input):
items = []
start = self.startParser.parse(input)
if start.result:
while True:
result = parser(input)
if result.result:
results.append(result.node)
snap = input.snapshot()
else:
input.reset(snap)
return ParseResult.OK(createNode(results, pos) if len(results) > 0 else NoneNode())
end = self.endParser.parse(input)
if end.result:
return ParseResult.OK(self.createNode(start.node, items, end.node))
item = self.itemParser.parse(input)
if not item.result:
return ParseResult.FAIL()
items.append(item.node)
return ParseResult.FAIL()
def _grammarRules(self, output):
output.append(f"{self.name} -> {self.startParser.name} {self.itemParser.name}* {self.endParser.name}")
self.startParser._grammarRules(output)
self.itemParser._grammarRules(output)
self.endParser._grammarRules(output)
return Parser(parse, name, parsers=[parser])

View File

@@ -1,14 +1,32 @@
import sys
from smnp.ast.node.atom import AtomParser
from smnp.ast.node.chain import ChainParser
from smnp.ast.node.list import ListParser
from smnp.ast.node.model import Node
from smnp.error.base import SmnpException
from smnp.program.interpreter import Interpreter
from smnp.token.tokenizer import tokenize
def main():
try:
#stdLibraryEnv = loadStandardLibrary()
Interpreter.interpretFile(sys.argv[1], printTokens=True, printAst=True, execute=False, baseEnvironment=None)
#draft()
# stdLibraryEnv = loadStandardLibrary()
# Interpreter.interpretFile(sys.argv[1], printTokens=True, printAst=True, execute=False, baseEnvironment=None)
# draft()
class TestNode(Node):
def __init__(self, children):
super().__init__((-1, -1))
self.children = children
tokens = tokenize(['[1, 2]'])
parser = ListParser()
#print(parser.grammar())
res = parser.parse(tokens)
print()
if res.result:
res.node.print()
else:
print("nie sparsowano")
except SmnpException as e:
print(e.message())

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