From 3bbacad83bee9af13b0700bec1968cd6d1657d97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Pluta?= Date: Thu, 11 Jul 2019 00:08:12 +0200 Subject: [PATCH] Add support for maps --- smnp/ast/node/atom.py | 23 ++++++++++++++-- smnp/ast/node/chain.py | 2 ++ smnp/ast/node/map.py | 62 +++++++++++++++--------------------------- 3 files changed, 44 insertions(+), 43 deletions(-) diff --git a/smnp/ast/node/atom.py b/smnp/ast/node/atom.py index 9d7187d..ac922be 100644 --- a/smnp/ast/node/atom.py +++ b/smnp/ast/node/atom.py @@ -38,9 +38,12 @@ class NoteLiteral(Atom): class BoolLiteral(Atom): pass -def AtomParser(input): - from smnp.ast.node.identifier import IdentifierParser +class TypeLiteral(Atom): + pass + + +def LiteralParser(input): integerParser = Parser.oneOf( Parser.terminalParser(TokenType.INTEGER, lambda val, pos: IntegerLiteral.withValue(int(val), pos)), Parser.allOf( @@ -50,11 +53,25 @@ def AtomParser(input): ) ) - parser = Parser.oneOf( + return Parser.oneOf( integerParser, Parser.terminalParser(TokenType.STRING, lambda val, pos: StringLiteral.withValue(val, pos)), Parser.terminalParser(TokenType.NOTE, lambda val, pos: NoteLiteral.withValue(val, pos)), Parser.terminalParser(TokenType.BOOL, lambda val, pos: BoolLiteral.withValue(val, pos)), + Parser.terminalParser(TokenType.TYPE, lambda val, pos: TypeLiteral.withValue(val, pos)), + )(input) + + +def AtomParser(input): + from smnp.ast.node.identifier import IdentifierParser + + + parser = Parser.oneOf( + LiteralParser, + Parser.terminalParser(TokenType.STRING, lambda val, pos: StringLiteral.withValue(val, pos)), + Parser.terminalParser(TokenType.NOTE, lambda val, pos: NoteLiteral.withValue(val, pos)), + Parser.terminalParser(TokenType.BOOL, lambda val, pos: BoolLiteral.withValue(val, pos)), + Parser.terminalParser(TokenType.TYPE, lambda val, pos: TypeLiteral.withValue(val, pos)), IdentifierParser, ) diff --git a/smnp/ast/node/chain.py b/smnp/ast/node/chain.py index 5476bea..8137869 100644 --- a/smnp/ast/node/chain.py +++ b/smnp/ast/node/chain.py @@ -1,5 +1,6 @@ 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 @@ -11,6 +12,7 @@ class Chain(Valuable): itemParser = Parser.oneOf( ListParser, + MapParser, AtomParser, ) diff --git a/smnp/ast/node/map.py b/smnp/ast/node/map.py index d477250..0f8c19f 100644 --- a/smnp/ast/node/map.py +++ b/smnp/ast/node/map.py @@ -1,20 +1,12 @@ -from smnp.ast.node.bool import BoolLiteralNode -from smnp.ast.node.expression import ExpressionNode -from smnp.ast.node.integer import IntegerLiteralNode +from smnp.ast.node.atom import LiteralParser from smnp.ast.node.iterable import abstractIterableParser -from smnp.ast.node.none import NoneNode -from smnp.ast.node.note import NoteLiteralNode -from smnp.ast.node.operator import LeftAssociativeOperatorNode -from smnp.ast.node.string import StringLiteralNode -from smnp.ast.node.type import TypeNode +from smnp.ast.node.model import Node +from smnp.ast.node.operator import BinaryOperator, Operator from smnp.ast.parser import Parser from smnp.token.type import TokenType -class MapEntry(ExpressionNode): - def __init__(self, pos): - super().__init__(pos) - self.children = [NoneNode(), NoneNode()] +class MapEntry(BinaryOperator): @property def key(self): @@ -26,39 +18,29 @@ class MapEntry(ExpressionNode): @property def value(self): - return self[1] + return self[2] @value.setter def value(self, value): - self[1] = value + self[2] = value -class MapNode(LeftAssociativeOperatorNode): - @classmethod - def _lhsParser(cls): - return abstractIterableParser(MapNode, TokenType.OPEN_CURLY, TokenType.CLOSE_CURLY, cls._entryParser()) +class Map(Node): + pass - @classmethod - def _entryParser(cls): - def createNode(key, arrow, value): - node = MapEntry(key.pos) - node.key = key - node.value = value - return node - return Parser.allOf( - cls._keyParser(), - Parser.terminalParser(TokenType.ARROW), - ExpressionNode.parse, - createNode=createNode - ) +def MapParser(input): + from smnp.ast.node.expression import MaxPrecedenceExpressionParser + keyParser = LiteralParser + valueParser = MaxPrecedenceExpressionParser - @classmethod - def _keyParser(cls): - return Parser.oneOf( - IntegerLiteralNode.literalParser(), - StringLiteralNode.literalParser(), - NoteLiteralNode.literalParser(), - BoolLiteralNode.literalParser(), - TypeNode.parse - ) \ No newline at end of file + mapEntryParser = Parser.allOf( + keyParser, + Parser.terminalParser(TokenType.ARROW, createNode=Operator.withValue), + valueParser, + createNode=MapEntry.withValues + ) + + mapParser = abstractIterableParser(Map, TokenType.OPEN_CURLY, TokenType.CLOSE_CURLY, mapEntryParser) + + return Parser(mapParser, "map", [mapParser])(input)