diff --git a/smnp/ast/node/condition.py b/smnp/ast/node/condition.py new file mode 100644 index 0000000..8aceac3 --- /dev/null +++ b/smnp/ast/node/condition.py @@ -0,0 +1,42 @@ +from smnp.ast.node.model import Node +from smnp.ast.node.none import NoneNode + + +class IfElse(Node): + def __init__(self, pos): + super().__init__(pos) + self.children = [NoneNode(), NoneNode(), NoneNode()] + + @property + def condition(self): + return self[0] + + @condition.setter + def condition(self, value): + self[0] = value + + @property + def ifNode(self): + return self[1] + + @ifNode.setter + def ifNode(self, value): + self[1] = value + + @property + def elseNode(self): + return self[2] + + @elseNode.setter + def elseNode(self, value): + self[2] = value + + @classmethod + def createNode(cls, ifNode, condition, elseNode=NoneNode()): + node = cls(ifNode.pos) + node.ifNode = ifNode + node.condition = condition + node.elseNode = elseNode + return node + + diff --git a/smnp/ast/node/expression.py b/smnp/ast/node/expression.py index 40fc7e7..f3f83e7 100644 --- a/smnp/ast/node/expression.py +++ b/smnp/ast/node/expression.py @@ -1,3 +1,4 @@ +from smnp.ast.node.condition import IfElse from smnp.ast.node.operator import BinaryOperator from smnp.ast.node.term import TermParser from smnp.ast.node.valuable import Valuable @@ -8,17 +9,56 @@ from smnp.token.type import TokenType class Expression(Valuable): pass -ExpressionParser = Parser.leftAssociativeOperatorParser(TermParser, [TokenType.PLUS, TokenType.MINUS], TermParser, - lambda left, op, right: Expression.withValue(BinaryOperator.withValues(left, op, right))) -Expression2Parser = Parser.leftAssociativeOperatorParser(ExpressionParser, [TokenType.RELATION], ExpressionParser, - lambda left, op, right: Expression.withValue(BinaryOperator.withValues(left, op, right))) +def ExpressionParser(input): + return Parser.leftAssociativeOperatorParser( + TermParser, + [TokenType.PLUS, TokenType.MINUS], + TermParser, + lambda left, op, right: Expression.withValue(BinaryOperator.withValues(left, op, right)) + )(input) -Expression3Parser = Parser.leftAssociativeOperatorParser(Expression2Parser, [TokenType.AND], Expression2Parser, - lambda left, op, right: Expression.withValue(BinaryOperator.withValues(left, op, right))) -Expression4Parser = Parser.leftAssociativeOperatorParser(Expression3Parser, [TokenType.OR], Expression3Parser, - lambda left, op, right: Expression.withValue(BinaryOperator.withValues(left, op, right))) +def Expression2Parser(input): + return Parser.leftAssociativeOperatorParser( + ExpressionParser, + [TokenType.RELATION], + ExpressionParser, + lambda left, op, right: Expression.withValue(BinaryOperator.withValues(left, op, right)) + )(input) + + +def Expression3Parser(input): + return Parser.leftAssociativeOperatorParser( + Expression2Parser, + [TokenType.AND], + Expression2Parser, + lambda left, op, right: Expression.withValue(BinaryOperator.withValues(left, op, right)) + )(input) + + +def Expression4Parser(input): + exprParser = Parser.leftAssociativeOperatorParser( + Expression3Parser, + [TokenType.OR], + Expression3Parser, + lambda left, op, right: Expression.withValue(BinaryOperator.withValues(left, op, right)) + ) + + ifElseExpression = Parser.allOf( + exprParser, + Parser.terminalParser(TokenType.IF), + Expression4Parser, + Parser.terminalParser(TokenType.ELSE), + Expression4Parser, + createNode=lambda ifNode, _, condition, __, elseNode: IfElse.createNode(ifNode, condition, elseNode) + ) + + return Parser.oneOf( + ifElseExpression, + exprParser, + )(input) + MaxPrecedenceExpressionParser = Expression4Parser diff --git a/smnp/token/tokenizer.py b/smnp/token/tokenizer.py index b0e3015..2e23425 100644 --- a/smnp/token/tokenizer.py +++ b/smnp/token/tokenizer.py @@ -51,9 +51,11 @@ tokenizers = ( separated(defaultTokenizer(TokenType.EXTEND)), separated(defaultTokenizer(TokenType.IMPORT)), separated(defaultTokenizer(TokenType.FROM)), + separated(defaultTokenizer(TokenType.ELSE)), separated(defaultTokenizer(TokenType.AND)), separated(defaultTokenizer(TokenType.NOT)), separated(defaultTokenizer(TokenType.AS)), + separated(defaultTokenizer(TokenType.IF)), separated(defaultTokenizer(TokenType.OR)), # Identifier (couldn't be before keywords!) diff --git a/smnp/token/type.py b/smnp/token/type.py index 854b412..35799fd 100644 --- a/smnp/token/type.py +++ b/smnp/token/type.py @@ -36,6 +36,8 @@ class TokenType(Enum): EXTEND = 'extend' IMPORT = 'import' FROM = 'from' + ELSE = 'else' + IF = 'if' AS = 'as' IDENTIFIER = 'identifier' COMMENT = 'comment'