Create parsers for literals (atoms)

This commit is contained in:
Bartłomiej Pluta
2019-07-10 21:17:16 +02:00
parent 66554f6c37
commit e31dab52f6
7 changed files with 105 additions and 33 deletions

57
smnp/ast/node/atom.py Normal file
View File

@@ -0,0 +1,57 @@
from smnp.ast.node.model import Node
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class Atom(Node):
def __init__(self, pos):
super().__init__(pos)
self.children = [None]
@property
def value(self):
return self[0]
@value.setter
def value(self, value):
self[0] = value
@classmethod
def withValue(cls, value, pos):
node = cls(pos)
node.value = value
return node
class IntegerLiteral(Atom):
pass
class StringLiteral(Atom):
pass
class NoteLiteral(Atom):
pass
class BoolLiteral(Atom):
pass
integerParser = 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)),
createNode=lambda minus, integer: IntegerLiteral.withValue(-integer.value, minus.pos)
)
)
parser = 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)),
)
AtomParser = Parser(parser, "atom", parser)

2
smnp/ast/node/chain.py Normal file
View File

@@ -0,0 +1,2 @@

View File

@@ -47,7 +47,7 @@ class Node:
self._print(first=True)
def _print(self, prefix="", last=True, first=False):
print(prefix, '' if first else '└─' if last else '├─', self.__class__.__name__, sep="")
print(prefix, '' if first else '└─' if last else '├─', self.__class__.__name__, f" (line {self.pos[0]+1}, col {self.pos[1]+1})", sep="")
prefix += ' ' if last else ''
for i, child in enumerate(self.children):
last = i == len(self.children) - 1

View File

@@ -1,32 +1,44 @@
from smnp.ast.node.expression import ExpressionNode
from smnp.ast.node.extend import ExtendNode
from smnp.ast.node.function import FunctionDefinitionNode
from smnp.ast.node.imports import ImportNode
from smnp.ast.node.atom import AtomParser
from smnp.ast.node.model import Node, ParseResult
from smnp.ast.node.statement import StatementNode
from smnp.ast.parser import Parser
from smnp.error.syntax import SyntaxException
class Program(Node):
def __init__(self):
super().__init__((-1, -1))
@classmethod
def _parse(cls, input):
def parseToken(input):
return Parser.oneOf(
FunctionDefinitionNode.parse,
ExtendNode.parse,
ExpressionNode.parse,
ImportNode.parse,
StatementNode.parse,
exception = SyntaxException(f"Invalid statement: {input.currentToEndOfLine()}", input.current().pos)
)(input)
def parse(input):
root = Program()
while input.hasCurrent():
result = Parser.oneOf(
# Start Symbol
root = Program()
while input.hasCurrent():
result = parseToken(input)
if result.result:
root.append(result.node)
return ParseResult.OK(root)
#TODO -> temporary (to remove):
AtomParser
)(input)
if result.result:
root.append(result.node)
return ParseResult.OK(root)
ProgramParser = Parser(parse, name="program")
# @classmethod
# def _parse(cls, input):
# def parseToken(input):
# return Parser.oneOf(
# FunctionDefinitionNode.parse,
# ExtendNode.parse,
# ExpressionNode.parse,
# ImportNode.parse,
# StatementNode.parse,
# exception = SyntaxException(f"Invalid statement: {input.currentToEndOfLine()}", input.current().pos)
# )(input)
#
# root = Program()
# while input.hasCurrent():
# result = parseToken(input)
# if result.result:
# root.append(result.node)
# return ParseResult.OK(root)

View File

@@ -5,8 +5,8 @@ from smnp.error.syntax import SyntaxException
def parse(input):
from smnp.ast.node.program import Program
return Program.parse(input).node
from smnp.ast.node.program import ProgramParser
return ProgramParser(input).node
class Parser:
@@ -58,7 +58,7 @@ class Parser:
return ParseResult.FAIL()
return Parser(parse, expectedType.name.lower())
return Parser(parse, name=expectedType.name.lower())
# oneOf -> a | b | c | ...
@staticmethod

View File

@@ -31,7 +31,7 @@ class Operation(Node):
return self[2]
def atom():
return Parser.terminalParser(TokenType.INTEGER, lambda val, pos: Atom(val, pos))
return Parser.oneOfTerminals(TokenType.INTEGER, TokenType.NOTE, TokenType.STRING, createNode=lambda val, pos: Atom(val, pos))
def chain():
return Parser.leftAssociativeOperatorParser(atom(), [TokenType.DOT], atom(), lambda left, op, right: Operation(left, op, right, op.pos), name="chain")
@@ -60,8 +60,7 @@ def evaluate(node):
def draft():
tokens = tokenize(['2**3/2 + 10 - 2'])
tokens = tokenize(['"fesf fe" + "fsefsef" + "fsefs"'])
e = expr()
node = e(tokens).node
node.print()
print(evaluate(node))

View File

@@ -1,12 +1,14 @@
from smnp.calc import draft
import sys
from smnp.error.base import SmnpException
from smnp.program.interpreter import Interpreter
def main():
try:
#stdLibraryEnv = loadStandardLibrary()
#Interpreter.interpretFile(sys.argv[1], printTokens=False, printAst=True, execute=False, baseEnvironment=stdLibraryEnv)
draft()
Interpreter.interpretFile(sys.argv[1], printTokens=False, printAst=True, execute=False, baseEnvironment=None)
#draft()
except SmnpException as e:
print(e.message())