Create simple calc as test draft
This commit is contained in:
@@ -93,22 +93,50 @@ class Parser:
|
|||||||
|
|
||||||
# leftAssociative -> left | left OP right
|
# leftAssociative -> left | left OP right
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def leftAssociativeOperatorParser(leftParser, operatorTokenType, rightParser, createNode):
|
def leftAssociativeOperatorParser(leftParser, operatorTokenTypes, rightParser, createNode):
|
||||||
from smnp.ast.node.operator import OperatorNode
|
from smnp.ast.node.operator import OperatorNode
|
||||||
|
|
||||||
def parse(input):
|
def parse(input):
|
||||||
|
operatorParser = Parser.oneOfTerminals(*operatorTokenTypes, createNode=lambda val, pos: OperatorNode.withChildren([val], pos))
|
||||||
left = leftParser(input)
|
left = leftParser(input)
|
||||||
if left.result:
|
if left.result:
|
||||||
operator = Parser.terminalParser(operatorTokenType, lambda val, pos: OperatorNode.withChildren([val], pos))(input)
|
operator = operatorParser(input)
|
||||||
while operator.result:
|
while operator.result:
|
||||||
right = rightParser(input)
|
right = rightParser(input)
|
||||||
left = ParseResult.OK(createNode(left.node, operator.node, right.node))
|
left = ParseResult.OK(createNode(left.node, operator.node, right.node))
|
||||||
operator = Parser.terminalParser(operatorTokenType, lambda val, pos: OperatorNode.withChildren([val], pos))(input)
|
operator = operatorParser(input)
|
||||||
return left
|
return left
|
||||||
|
|
||||||
return ParseResult.FAIL()
|
return ParseResult.FAIL()
|
||||||
|
|
||||||
return parse
|
return parse
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def oneOfTerminals(*tokenTypes, createNode=None):
|
||||||
|
return Parser.oneOf(*[ Parser.terminalParser(expectedType, createNode=createNode) for expectedType in tokenTypes ])
|
||||||
|
|
||||||
|
# leftAssociative -> left OP right | right
|
||||||
|
@staticmethod
|
||||||
|
def leftAssociativeOperatorOrRightParser(leftParser, operatorTokenType, rightParser, createNode):
|
||||||
|
from smnp.ast.node.operator import OperatorNode
|
||||||
|
def parse(input):
|
||||||
|
left = leftParser(input)
|
||||||
|
oneAtLeast = False
|
||||||
|
if left.result:
|
||||||
|
operator = Parser.terminalParser(operatorTokenType, lambda val, pos: OperatorNode.withChildren([val], pos))(input)
|
||||||
|
while operator.result:
|
||||||
|
oneAtLeast = True
|
||||||
|
right = rightParser(input)
|
||||||
|
left = ParseResult.OK(createNode(left.node, operator.node, right.node))
|
||||||
|
operator = Parser.terminalParser(operatorTokenType, lambda val, pos: OperatorNode.withChildren([val], pos))(input)
|
||||||
|
|
||||||
|
if oneAtLeast:
|
||||||
|
return left
|
||||||
|
|
||||||
|
return ParseResult.FAIL()
|
||||||
|
|
||||||
|
return Parser.oneOf(parse, rightParser)
|
||||||
|
|
||||||
# loop -> start item* end
|
# loop -> start item* end
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def loop(startParser, itemParser, endParser, createNode):
|
def loop(startParser, itemParser, endParser, createNode):
|
||||||
@@ -154,6 +182,10 @@ class Parser:
|
|||||||
|
|
||||||
return parse
|
return parse
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def epsilon():
|
||||||
|
return lambda *args: ParseResult.OK(NoneNode())
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def many(parser, createNode):
|
def many(parser, createNode):
|
||||||
def parse(input):
|
def parse(input):
|
||||||
|
|||||||
66
smnp/calc.py
Normal file
66
smnp/calc.py
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
from smnp.ast.node.model import Node
|
||||||
|
from smnp.ast.parser import Parser
|
||||||
|
from smnp.token.tokenizer import tokenize
|
||||||
|
from smnp.token.type import TokenType
|
||||||
|
|
||||||
|
|
||||||
|
class Atom(Node):
|
||||||
|
def __init__(self, value, pos):
|
||||||
|
super().__init__(pos)
|
||||||
|
self.children = [value]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def value(self):
|
||||||
|
return self[0]
|
||||||
|
|
||||||
|
class Operation(Node):
|
||||||
|
def __init__(self, left, op, right, pos):
|
||||||
|
super().__init__(pos)
|
||||||
|
self.children = [left, op, right]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def left(self):
|
||||||
|
return self[0]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def operator(self):
|
||||||
|
return self[1]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def right(self):
|
||||||
|
return self[2]
|
||||||
|
|
||||||
|
def atom(input):
|
||||||
|
return Parser.terminalParser(TokenType.INTEGER, lambda val, pos: Atom(val, pos))(input)
|
||||||
|
|
||||||
|
def chain(input):
|
||||||
|
return Parser.leftAssociativeOperatorParser(atom, [TokenType.DOT], atom, lambda left, op, right: Operation(left, op, right, op.pos))(input)
|
||||||
|
|
||||||
|
def factor(input):
|
||||||
|
return Parser.leftAssociativeOperatorParser(chain, [TokenType.DOUBLE_ASTERISK], chain, lambda left, op, right: Operation(left, op, right, op.pos))(input)
|
||||||
|
|
||||||
|
def term(input):
|
||||||
|
return Parser.leftAssociativeOperatorParser(factor, [TokenType.ASTERISK, TokenType.SLASH], factor, lambda left, op, right: Operation(left, op, right, op.pos))(input)
|
||||||
|
|
||||||
|
def expr(input):
|
||||||
|
return Parser.leftAssociativeOperatorParser(term, [TokenType.PLUS, TokenType.MINUS], term, lambda left, op, right: Operation(left, op, right, op.pos))(input)
|
||||||
|
|
||||||
|
def evaluate(node):
|
||||||
|
if type(node) == Atom:
|
||||||
|
return node.value
|
||||||
|
lhs = evaluate(node.left)
|
||||||
|
rhs = evaluate(node.right)
|
||||||
|
return {
|
||||||
|
"+": int(lhs) + int(rhs),
|
||||||
|
"*": int(lhs) * int(rhs),
|
||||||
|
"-": int(lhs) - int(rhs),
|
||||||
|
"/": int(lhs) / int(rhs),
|
||||||
|
"**": int(lhs) ** int(rhs)
|
||||||
|
}[node.operator.value]
|
||||||
|
|
||||||
|
def draft():
|
||||||
|
|
||||||
|
tokens = tokenize(['2 + 2 * 2 / 2'])
|
||||||
|
node = expr(tokens).node
|
||||||
|
node.print()
|
||||||
|
print(evaluate(node))
|
||||||
10
smnp/main.py
10
smnp/main.py
@@ -1,14 +1,12 @@
|
|||||||
import sys
|
from smnp.calc import draft
|
||||||
|
|
||||||
from smnp.error.base import SmnpException
|
from smnp.error.base import SmnpException
|
||||||
from smnp.library.loader import loadStandardLibrary
|
|
||||||
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=stdLibraryEnv)
|
||||||
|
draft()
|
||||||
|
|
||||||
except SmnpException as e:
|
except SmnpException as e:
|
||||||
print(e.message())
|
print(e.message())
|
||||||
|
|||||||
@@ -20,11 +20,14 @@ tokenizers = (
|
|||||||
defaultTokenizer(TokenType.CLOSE_SQUARE),
|
defaultTokenizer(TokenType.CLOSE_SQUARE),
|
||||||
defaultTokenizer(TokenType.OPEN_ANGLE),
|
defaultTokenizer(TokenType.OPEN_ANGLE),
|
||||||
defaultTokenizer(TokenType.CLOSE_ANGLE),
|
defaultTokenizer(TokenType.CLOSE_ANGLE),
|
||||||
|
defaultTokenizer(TokenType.DOUBLE_ASTERISK),
|
||||||
defaultTokenizer(TokenType.ASTERISK),
|
defaultTokenizer(TokenType.ASTERISK),
|
||||||
defaultTokenizer(TokenType.ASSIGN),
|
defaultTokenizer(TokenType.ASSIGN),
|
||||||
defaultTokenizer(TokenType.ARROW),
|
defaultTokenizer(TokenType.ARROW),
|
||||||
defaultTokenizer(TokenType.COMMA),
|
defaultTokenizer(TokenType.COMMA),
|
||||||
|
defaultTokenizer(TokenType.SLASH),
|
||||||
defaultTokenizer(TokenType.MINUS),
|
defaultTokenizer(TokenType.MINUS),
|
||||||
|
defaultTokenizer(TokenType.PLUS),
|
||||||
defaultTokenizer(TokenType.DOTS),
|
defaultTokenizer(TokenType.DOTS),
|
||||||
defaultTokenizer(TokenType.AMP),
|
defaultTokenizer(TokenType.AMP),
|
||||||
defaultTokenizer(TokenType.DOT),
|
defaultTokenizer(TokenType.DOT),
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from enum import Enum
|
|||||||
|
|
||||||
|
|
||||||
class TokenType(Enum):
|
class TokenType(Enum):
|
||||||
|
DOUBLE_ASTERISK = '**'
|
||||||
OPEN_CURLY = '{'
|
OPEN_CURLY = '{'
|
||||||
CLOSE_CURLY = '}'
|
CLOSE_CURLY = '}'
|
||||||
OPEN_PAREN = '('
|
OPEN_PAREN = '('
|
||||||
@@ -14,7 +15,9 @@ class TokenType(Enum):
|
|||||||
ASSIGN = '='
|
ASSIGN = '='
|
||||||
ARROW = '->'
|
ARROW = '->'
|
||||||
COMMA = ','
|
COMMA = ','
|
||||||
|
SLASH = '/'
|
||||||
MINUS = '-'
|
MINUS = '-'
|
||||||
|
PLUS = '+'
|
||||||
DOTS = '...'
|
DOTS = '...'
|
||||||
AMP = '&'
|
AMP = '&'
|
||||||
DOT = '.'
|
DOT = '.'
|
||||||
|
|||||||
Reference in New Issue
Block a user