Create expression precendence level

This commit is contained in:
Bartłomiej Pluta
2019-07-10 22:27:44 +02:00
parent 1d573c8c80
commit 4018bcddc7
10 changed files with 390 additions and 346 deletions

View File

@@ -1,11 +1,12 @@
from smnp.ast.node.atom import AtomParser
from smnp.ast.node.list import ListParser
from smnp.ast.node.operator import BinaryOperator
from smnp.ast.node.valuable import Valuable
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class Chain(BinaryOperator):
class Chain(Valuable):
pass
itemParser = Parser.oneOf(
@@ -14,5 +15,5 @@ itemParser = Parser.oneOf(
)
ChainParser = Parser.leftAssociativeOperatorParser(itemParser, [TokenType.DOT], itemParser,
lambda left, op, right: Chain.withValues(left, op, right))
lambda left, op, right: Chain.withValue(BinaryOperator.withValues(left, op, right)))

View File

@@ -1,71 +1,78 @@
from smnp.ast.node.asterisk import AsteriskNode
from smnp.ast.node.model import Node
from smnp.ast.node.none import NoneNode
from smnp.ast.node.statement import StatementNode
from smnp.ast.node.operator import BinaryOperator
from smnp.ast.node.term import TermParser
from smnp.ast.node.valuable import Valuable
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class ExpressionNode(Node):
def __init__(self, pos):
super().__init__(pos, [NoneNode()])
@property
def value(self):
return self[0]
class Expression(Valuable):
pass
@value.setter
def value(self, v):
self[0] = v
ExpressionParser = Parser.leftAssociativeOperatorParser(TermParser, [TokenType.PLUS, TokenType.MINUS], TermParser,
lambda left, op, right: Expression.withValue(BinaryOperator.withValues(left, op, right)))
@classmethod
def withValue(cls, val, pos):
node = cls(pos)
node.value = val
return node
@classmethod
def _parse(cls, input):
return Parser.oneOf(
cls._asteriskParser(),
cls._expressionParser(),
)(input)
@classmethod
def _asteriskParser(cls):
def createNode(iterator, asterisk, statement):
node = AsteriskNode(asterisk.pos)
node.iterator = iterator
node.statement = statement
return node
return Parser.allOf(
cls._expressionParser(),
Parser.terminalParser(TokenType.ASTERISK),
Parser.doAssert(StatementNode.parse, 'statement'),
createNode=createNode
)
@classmethod
def _expressionParser(cls):
from smnp.ast.node.integer import IntegerLiteralNode
from smnp.ast.node.string import StringLiteralNode
from smnp.ast.node.note import NoteLiteralNode
from smnp.ast.node.bool import BoolLiteralNode
from smnp.ast.node.identifier import IdentifierNode
from smnp.ast.node.list import List
from smnp.ast.node.map import MapNode
from smnp.ast.node.type import TypeNode
return Parser.oneOf(
IntegerLiteralNode.parse,
StringLiteralNode.parse,
NoteLiteralNode.parse,
BoolLiteralNode.parse,
IdentifierNode.parse,
MapNode.parse,
List.parse,
TypeNode.parse,
)
#
# class ExpressionNode(Node):
# def __init__(self, pos):
# super().__init__(pos, [NoneNode()])
#
# @property
# def value(self):
# return self[0]
#
#
# @value.setter
# def value(self, v):
# self[0] = v
#
#
# @classmethod
# def withValue(cls, val, pos):
# node = cls(pos)
# node.value = val
# return node
#
# @classmethod
# def _parse(cls, input):
# return Parser.oneOf(
# cls._asteriskParser(),
# cls._expressionParser(),
# )(input)
#
# @classmethod
# def _asteriskParser(cls):
# def createNode(iterator, asterisk, statement):
# node = AsteriskNode(asterisk.pos)
# node.iterator = iterator
# node.statement = statement
# return node
#
# return Parser.allOf(
# cls._expressionParser(),
# Parser.terminalParser(TokenType.ASTERISK),
# Parser.doAssert(StatementNode.parse, 'statement'),
# createNode=createNode
# )
#
# @classmethod
# def _expressionParser(cls):
# from smnp.ast.node.integer import IntegerLiteralNode
# from smnp.ast.node.string import StringLiteralNode
# from smnp.ast.node.note import NoteLiteralNode
# from smnp.ast.node.bool import BoolLiteralNode
# from smnp.ast.node.identifier import IdentifierNode
# from smnp.ast.node.list import List
# from smnp.ast.node.map import MapNode
# from smnp.ast.node.type import TypeNode
#
# return Parser.oneOf(
# IntegerLiteralNode.parse,
# StringLiteralNode.parse,
# NoteLiteralNode.parse,
# BoolLiteralNode.parse,
# IdentifierNode.parse,
# MapNode.parse,
# List.parse,
# TypeNode.parse,
# )

View File

@@ -1,70 +1,70 @@
from smnp.ast.node.block import BlockNode
from smnp.ast.node.function import FunctionDefinitionNode
from smnp.ast.node.identifier import IdentifierNode
from smnp.ast.node.none import NoneNode
from smnp.ast.node.statement import StatementNode
from smnp.ast.node.type import TypeNode
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class ExtendNode(StatementNode):
def __init__(self, pos):
super().__init__(pos)
self.children = [NoneNode(), NoneNode(), NoneNode()]
@property
def type(self):
return self[0]
@type.setter
def type(self, value):
self[0] = value
@property
def variable(self):
return self[1]
@variable.setter
def variable(self, value):
self[1] = value
@property
def methods(self):
return self[2]
@methods.setter
def methods(self, value):
self[2] = value
@classmethod
def _parse(cls, input):
def createNode(extend, type, asKeyword, variable, methods):
node = ExtendNode(extend.pos)
node.type = type
node.variable = variable
node.methods = methods
return node
return Parser.allOf(
Parser.terminalParser(TokenType.EXTEND),
Parser.doAssert(TypeNode.parse, "type being extended"),
Parser.terminalParser(TokenType.AS, doAssert=True),
Parser.doAssert(IdentifierNode.identifierParser(), "variable name"),
Parser.doAssert(cls._methodsDeclarationsParser(), "methods declarations"),
createNode=createNode
)(input)
@classmethod
def _methodsDeclarationsParser(cls):
def createNode(openBracket, items, closeBracket):
node = BlockNode(openBracket.pos)
node.children = items
return node
return Parser.loop(
Parser.terminalParser(TokenType.OPEN_CURLY),
Parser.doAssert(FunctionDefinitionNode.parse, f"method declaration or '{TokenType.CLOSE_CURLY.key}'"),
Parser.terminalParser(TokenType.CLOSE_CURLY),
createNode=createNode
)
# from smnp.ast.node.block import BlockNode
# from smnp.ast.node.function import FunctionDefinitionNode
# from smnp.ast.node.identifier import IdentifierNode
# from smnp.ast.node.none import NoneNode
# from smnp.ast.node.statement import StatementNode
# from smnp.ast.node.type import TypeNode
# from smnp.ast.parser import Parser
# from smnp.token.type import TokenType
#
#
# class ExtendNode(StatementNode):
# def __init__(self, pos):
# super().__init__(pos)
# self.children = [NoneNode(), NoneNode(), NoneNode()]
#
# @property
# def type(self):
# return self[0]
#
# @type.setter
# def type(self, value):
# self[0] = value
#
# @property
# def variable(self):
# return self[1]
#
# @variable.setter
# def variable(self, value):
# self[1] = value
#
# @property
# def methods(self):
# return self[2]
#
# @methods.setter
# def methods(self, value):
# self[2] = value
#
# @classmethod
# def _parse(cls, input):
# def createNode(extend, type, asKeyword, variable, methods):
# node = ExtendNode(extend.pos)
# node.type = type
# node.variable = variable
# node.methods = methods
# return node
#
# return Parser.allOf(
# Parser.terminalParser(TokenType.EXTEND),
# Parser.doAssert(TypeNode.parse, "type being extended"),
# Parser.terminalParser(TokenType.AS, doAssert=True),
# Parser.doAssert(IdentifierNode.identifierParser(), "variable name"),
# Parser.doAssert(cls._methodsDeclarationsParser(), "methods declarations"),
# createNode=createNode
# )(input)
#
# @classmethod
# def _methodsDeclarationsParser(cls):
# def createNode(openBracket, items, closeBracket):
# node = BlockNode(openBracket.pos)
# node.children = items
# return node
#
# return Parser.loop(
# Parser.terminalParser(TokenType.OPEN_CURLY),
# Parser.doAssert(FunctionDefinitionNode.parse, f"method declaration or '{TokenType.CLOSE_CURLY.key}'"),
# Parser.terminalParser(TokenType.CLOSE_CURLY),
# createNode=createNode
# )

View File

@@ -1,12 +1,30 @@
from smnp.ast.node.chain import ChainParser
from smnp.ast.node.operator import BinaryOperator
from smnp.ast.node.valuable import Valuable
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class Factor(BinaryOperator):
class Factor(Valuable):
pass
FactorParser = Parser.leftAssociativeOperatorParser(ChainParser, [TokenType.DOUBLE_ASTERISK], ChainParser,
lambda left, op, right: Factor.withValues(left, op, right))
powerFactor = Parser.leftAssociativeOperatorParser(ChainParser, [TokenType.DOUBLE_ASTERISK], ChainParser,
lambda left, op, right: Factor.withValue(BinaryOperator.withValues(left, op, right)))
def exprFactor():
from smnp.ast.node.expression import ExpressionParser
return Parser.allOf(
Parser.terminalParser(TokenType.OPEN_PAREN),
ExpressionParser,
Parser.terminalParser(TokenType.CLOSE_PAREN),
createNode=lambda open, expr, close: expr
)
def FactorParser(input):
return Parser.oneOf(
powerFactor,
exprFactor()
)(input)

View File

@@ -1,128 +1,128 @@
from smnp.ast.node.block import BlockNode
from smnp.ast.node.expression import ExpressionNode
from smnp.ast.node.identifier import IdentifierNode
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.statement import StatementNode
from smnp.ast.node.type import TypeNode, TypeSpecifier
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class ArgumentsDeclarationNode(Node):
@classmethod
def _parse(cls, input):
raise RuntimeError("This class is not supposed to be automatically called")
class VarargNode(Node):
pass
class ArgumentDefinitionNode(ExpressionNode):
def __init__(self, pos):
super().__init__(pos)
self.children.extend([NoneNode(), False])
@property
def type(self):
return self[0]
@type.setter
def type(self, value):
self[0] = value
@property
def variable(self):
return self[1]
@variable.setter
def variable(self, value):
self[1] = value
@property
def vararg(self):
return self[2]
@vararg.setter
def vararg(self, value):
self[2] = value
@classmethod
def parser(cls):
def createNode(type, variable, dots):
node = ArgumentDefinitionNode(type.pos)
node.type = type
node.variable = variable
node.vararg = isinstance(dots, VarargNode)
return node
return Parser.allOf(
Parser.optional(Parser.oneOf(
TypeNode.parse,
TypeSpecifier.parse
)),
Parser.doAssert(IdentifierNode.identifierParser(), "variable name"),
Parser.optional(Parser.terminalParser(TokenType.DOTS, lambda val, pos: VarargNode(pos))),
createNode=createNode
)
@classmethod
def _parse(cls, input):
#TODO
raise RuntimeError("Not implemented yet. There is still required work to correctly build AST related to IdentifierNode")
class FunctionDefinitionNode(StatementNode):
def __init__(self, pos):
super().__init__(pos)
self.children = [NoneNode(), NoneNode(), NoneNode()]
@property
def name(self):
return self[0]
@name.setter
def name(self, value):
self[0] = value
@property
def arguments(self):
return self[1]
@arguments.setter
def arguments(self, value):
self[1] = value
@property
def body(self):
return self[2]
@body.setter
def body(self, value):
self[2] = value
@classmethod
def _parse(cls, input):
def createNode(function, name, arguments, body):
node = FunctionDefinitionNode(function.pos)
node.name = name
node.arguments = arguments
node.body = body
return node
return Parser.allOf(
Parser.terminalParser(TokenType.FUNCTION),
Parser.doAssert(IdentifierNode.identifierParser(), "function name"),
Parser.doAssert(cls._argumentsDeclarationParser(), "arguments list"),
Parser.doAssert(BlockNode.parse, "function body"),
createNode=createNode
)(input)
@staticmethod
def _argumentsDeclarationParser():
return abstractIterableParser(ArgumentsDeclarationNode, TokenType.OPEN_PAREN, TokenType.CLOSE_PAREN, ArgumentDefinitionNode.parser())
# from smnp.ast.node.block import BlockNode
# from smnp.ast.node.expression import ExpressionNode
# from smnp.ast.node.identifier import IdentifierNode
# 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.statement import StatementNode
# from smnp.ast.node.type import TypeNode, TypeSpecifier
# from smnp.ast.parser import Parser
# from smnp.token.type import TokenType
#
#
# class ArgumentsDeclarationNode(Node):
#
# @classmethod
# def _parse(cls, input):
# raise RuntimeError("This class is not supposed to be automatically called")
#
#
# class VarargNode(Node):
# pass
#
#
# class ArgumentDefinitionNode(ExpressionNode):
# def __init__(self, pos):
# super().__init__(pos)
# self.children.extend([NoneNode(), False])
#
# @property
# def type(self):
# return self[0]
#
# @type.setter
# def type(self, value):
# self[0] = value
#
# @property
# def variable(self):
# return self[1]
#
# @variable.setter
# def variable(self, value):
# self[1] = value
#
# @property
# def vararg(self):
# return self[2]
#
# @vararg.setter
# def vararg(self, value):
# self[2] = value
#
#
# @classmethod
# def parser(cls):
# def createNode(type, variable, dots):
# node = ArgumentDefinitionNode(type.pos)
# node.type = type
# node.variable = variable
# node.vararg = isinstance(dots, VarargNode)
# return node
#
# return Parser.allOf(
# Parser.optional(Parser.oneOf(
# TypeNode.parse,
# TypeSpecifier.parse
# )),
# Parser.doAssert(IdentifierNode.identifierParser(), "variable name"),
# Parser.optional(Parser.terminalParser(TokenType.DOTS, lambda val, pos: VarargNode(pos))),
# createNode=createNode
# )
#
# @classmethod
# def _parse(cls, input):
# #TODO
# raise RuntimeError("Not implemented yet. There is still required work to correctly build AST related to IdentifierNode")
#
#
#
# class FunctionDefinitionNode(StatementNode):
# def __init__(self, pos):
# super().__init__(pos)
# self.children = [NoneNode(), NoneNode(), NoneNode()]
#
# @property
# def name(self):
# return self[0]
#
# @name.setter
# def name(self, value):
# self[0] = value
#
# @property
# def arguments(self):
# return self[1]
#
# @arguments.setter
# def arguments(self, value):
# self[1] = value
#
# @property
# def body(self):
# return self[2]
#
# @body.setter
# def body(self, value):
# self[2] = value
#
# @classmethod
# def _parse(cls, input):
# def createNode(function, name, arguments, body):
# node = FunctionDefinitionNode(function.pos)
# node.name = name
# node.arguments = arguments
# node.body = body
# return node
#
# return Parser.allOf(
# Parser.terminalParser(TokenType.FUNCTION),
# Parser.doAssert(IdentifierNode.identifierParser(), "function name"),
# Parser.doAssert(cls._argumentsDeclarationParser(), "arguments list"),
# Parser.doAssert(BlockNode.parse, "function body"),
# createNode=createNode
# )(input)
#
# @staticmethod
# def _argumentsDeclarationParser():
# return abstractIterableParser(ArgumentsDeclarationNode, TokenType.OPEN_PAREN, TokenType.CLOSE_PAREN, ArgumentDefinitionNode.parser())

View File

@@ -1,9 +1,5 @@
from smnp.ast.node.expression import ExpressionNode
from smnp.ast.node.model import Node
from smnp.ast.node.none import NoneNode
from smnp.ast.parser import Parser
from smnp.error.syntax import SyntaxException
from smnp.token.type import TokenType
class BinaryOperator(Node):
@@ -43,68 +39,68 @@ class BinaryOperator(Node):
node.right = right
return node
class LeftAssociativeOperatorNode(ExpressionNode):
def __init__(self, pos):
super().__init__(pos)
self.children = [NoneNode(), NoneNode(), NoneNode()]
@property
def left(self):
return self[0]
@left.setter
def left(self, value):
self[0] = value
@property
def operator(self):
return self[1]
@operator.setter
def operator(self, value):
self[1] = value
@property
def right(self):
return self[2]
@right.setter
def right(self, value):
self[2] = value
@classmethod
def _parse(cls, input):
def createNode(left, operator, right):
node = LeftAssociativeOperatorNode(right.pos)
node.left = left
node.operator = operator
node.right = right
return node
return Parser.leftAssociativeOperatorParser(
cls._lhsParser(),
TokenType.DOT,
cls._rhsParser(),
createNode=createNode
)(input)
@classmethod
def _lhsParser(cls):
raise RuntimeError(f"LHS parser is not implemented in {cls.__name__}")
@staticmethod
def _rhsParser():
from smnp.ast.node.identifier import IdentifierNode
return Parser.oneOf(
# TODO!!!
IdentifierNode._lhsParser(),
IdentifierNode._functionCallParser(),
exception=lambda input: SyntaxException(f"Expected property name or method call, found '{input.current().rawValue}'", input.currentPos())
)
#
# class LeftAssociativeOperatorNode(ExpressionNode):
# def __init__(self, pos):
# super().__init__(pos)
# self.children = [NoneNode(), NoneNode(), NoneNode()]
#
# @property
# def left(self):
# return self[0]
#
# @left.setter
# def left(self, value):
# self[0] = value
#
# @property
# def operator(self):
# return self[1]
#
# @operator.setter
# def operator(self, value):
# self[1] = value
#
# @property
# def right(self):
# return self[2]
#
# @right.setter
# def right(self, value):
# self[2] = value
#
# @classmethod
# def _parse(cls, input):
# def createNode(left, operator, right):
# node = LeftAssociativeOperatorNode(right.pos)
# node.left = left
# node.operator = operator
# node.right = right
# return node
#
# return Parser.leftAssociativeOperatorParser(
# cls._lhsParser(),
# TokenType.DOT,
# cls._rhsParser(),
# createNode=createNode
# )(input)
#
# @classmethod
# def _lhsParser(cls):
# raise RuntimeError(f"LHS parser is not implemented in {cls.__name__}")
#
# @staticmethod
# def _rhsParser():
# from smnp.ast.node.identifier import IdentifierNode
#
# return Parser.oneOf(
# # TODO!!!
# IdentifierNode._lhsParser(),
# IdentifierNode._functionCallParser(),
# exception=lambda input: SyntaxException(f"Expected property name or method call, found '{input.current().rawValue}'", input.currentPos())
# )
#
#
class Operator(Node):
def __init__(self, pos):
super().__init__(pos)

View File

@@ -1,5 +1,5 @@
from smnp.ast.node.expression import ExpressionParser
from smnp.ast.node.model import Node, ParseResult
from smnp.ast.node.term import TermParser
from smnp.ast.parser import Parser
@@ -15,7 +15,7 @@ def parse(input):
#TODO -> temporary (to remove):
TermParser
ExpressionParser
)(input)
if result.result:

View File

@@ -1,11 +1,12 @@
from smnp.ast.node.factor import FactorParser
from smnp.ast.node.operator import BinaryOperator
from smnp.ast.node.valuable import Valuable
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class Term(BinaryOperator):
class Term(Valuable):
pass
TermParser = Parser.leftAssociativeOperatorParser(FactorParser, [TokenType.ASTERISK, TokenType.SLASH], FactorParser,
lambda left, op, right: Term.withValues(left, op, right))
lambda left, op, right: Term.withValue(BinaryOperator.withValues(left, op, right)))

22
smnp/ast/node/valuable.py Normal file
View File

@@ -0,0 +1,22 @@
from smnp.ast.node.model import Node
from smnp.ast.node.none import NoneNode
class Valuable(Node):
def __init__(self, pos):
super().__init__(pos)
self.children = [NoneNode()]
@property
def value(self):
return self[0]
@value.setter
def value(self, value):
self[0] = value
@classmethod
def withValue(cls, value):
node = cls(value.pos)
node.value = value
return node