Create parsers for literals (atoms)
This commit is contained in:
57
smnp/ast/node/atom.py
Normal file
57
smnp/ast/node/atom.py
Normal 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
2
smnp/ast/node/chain.py
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ class Node:
|
|||||||
self._print(first=True)
|
self._print(first=True)
|
||||||
|
|
||||||
def _print(self, prefix="", last=True, first=False):
|
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 '│ '
|
prefix += ' ' if last else '│ '
|
||||||
for i, child in enumerate(self.children):
|
for i, child in enumerate(self.children):
|
||||||
last = i == len(self.children) - 1
|
last = i == len(self.children) - 1
|
||||||
|
|||||||
@@ -1,32 +1,44 @@
|
|||||||
from smnp.ast.node.expression import ExpressionNode
|
from smnp.ast.node.atom import AtomParser
|
||||||
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.model import Node, ParseResult
|
from smnp.ast.node.model import Node, ParseResult
|
||||||
from smnp.ast.node.statement import StatementNode
|
|
||||||
from smnp.ast.parser import Parser
|
from smnp.ast.parser import Parser
|
||||||
from smnp.error.syntax import SyntaxException
|
|
||||||
|
|
||||||
|
|
||||||
class Program(Node):
|
class Program(Node):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__((-1, -1))
|
super().__init__((-1, -1))
|
||||||
|
|
||||||
@classmethod
|
def parse(input):
|
||||||
def _parse(cls, input):
|
root = Program()
|
||||||
def parseToken(input):
|
while input.hasCurrent():
|
||||||
return Parser.oneOf(
|
result = Parser.oneOf(
|
||||||
FunctionDefinitionNode.parse,
|
# Start Symbol
|
||||||
ExtendNode.parse,
|
|
||||||
ExpressionNode.parse,
|
|
||||||
ImportNode.parse,
|
|
||||||
StatementNode.parse,
|
|
||||||
exception = SyntaxException(f"Invalid statement: {input.currentToEndOfLine()}", input.current().pos)
|
|
||||||
)(input)
|
|
||||||
|
|
||||||
root = Program()
|
|
||||||
while input.hasCurrent():
|
#TODO -> temporary (to remove):
|
||||||
result = parseToken(input)
|
AtomParser
|
||||||
if result.result:
|
)(input)
|
||||||
root.append(result.node)
|
|
||||||
return ParseResult.OK(root)
|
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)
|
||||||
@@ -5,8 +5,8 @@ from smnp.error.syntax import SyntaxException
|
|||||||
|
|
||||||
|
|
||||||
def parse(input):
|
def parse(input):
|
||||||
from smnp.ast.node.program import Program
|
from smnp.ast.node.program import ProgramParser
|
||||||
return Program.parse(input).node
|
return ProgramParser(input).node
|
||||||
|
|
||||||
|
|
||||||
class Parser:
|
class Parser:
|
||||||
@@ -58,7 +58,7 @@ class Parser:
|
|||||||
|
|
||||||
return ParseResult.FAIL()
|
return ParseResult.FAIL()
|
||||||
|
|
||||||
return Parser(parse, expectedType.name.lower())
|
return Parser(parse, name=expectedType.name.lower())
|
||||||
|
|
||||||
# oneOf -> a | b | c | ...
|
# oneOf -> a | b | c | ...
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class Operation(Node):
|
|||||||
return self[2]
|
return self[2]
|
||||||
|
|
||||||
def atom():
|
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():
|
def chain():
|
||||||
return Parser.leftAssociativeOperatorParser(atom(), [TokenType.DOT], atom(), lambda left, op, right: Operation(left, op, right, op.pos), name="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():
|
def draft():
|
||||||
|
|
||||||
tokens = tokenize(['2**3/2 + 10 - 2'])
|
tokens = tokenize(['"fesf fe" + "fsefsef" + "fsefs"'])
|
||||||
e = expr()
|
e = expr()
|
||||||
node = e(tokens).node
|
node = e(tokens).node
|
||||||
node.print()
|
node.print()
|
||||||
print(evaluate(node))
|
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
from smnp.calc import draft
|
import sys
|
||||||
|
|
||||||
from smnp.error.base import SmnpException
|
from smnp.error.base import SmnpException
|
||||||
|
from smnp.program.interpreter import Interpreter
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
try:
|
try:
|
||||||
#stdLibraryEnv = loadStandardLibrary()
|
#stdLibraryEnv = loadStandardLibrary()
|
||||||
#Interpreter.interpretFile(sys.argv[1], printTokens=False, printAst=True, execute=False, baseEnvironment=stdLibraryEnv)
|
Interpreter.interpretFile(sys.argv[1], printTokens=False, printAst=True, execute=False, baseEnvironment=None)
|
||||||
draft()
|
#draft()
|
||||||
|
|
||||||
except SmnpException as e:
|
except SmnpException as e:
|
||||||
print(e.message())
|
print(e.message())
|
||||||
|
|||||||
Reference in New Issue
Block a user