I am creating my own programming language and I'm stuck with a basic IF statement definition. It would look something like this:
IF a == 10 : a = a + 10
The : is something similar to brackets. I decided to create this because it's easier to see and easy to understand. As well as creating this, the variable definition looks something like this:
BOX a = 10
How can I make this work? Here's my actual code:
Lexer File
from sly import Lexer
#Creating a Lexer
class BasicLexer(Lexer):
tokens = { NAME, NUMBER, STRING, BOX, PROCESS, DOT }
ignore = '\t '
literals = { '=', '+', '-', '/', '*', '(', ')', ',', ';' }
# Defining tokens
DOT = r':'
PROCESS = r'PROCESS'
BOX = r'BOX'
NAME = r'[a-zA-Z_][a-zA-Z0-9_]*'
STRING = r'\".*?\"'
@_(r'\d+')
def NUMBER(self, t):
t.value = int(t.value)
return t
@_(r'COM.*')
def COMMENT(self, t):
pass
@_(r'\n+')
def newline(self, t):
self.lineno = t.value.count('\n')
Parser File
from sly import Parser
from lexer import BasicLexer
class BasicParser(Parser):
tokens = BasicLexer.tokens
precedence = (
('left', '+', '-'),
('left', '*', '/'),
('right', 'UMINUS'),
)
def __init__(self):
self.env = { }
@_('')
def statement(self, p):
pass
@_('PROCESS NAME "(" ")" DOT statement')
def statement(self, p):
return ('process_def', p.NAME, p.statement)
@_('NAME "(" ")"')
def statement(self, p):
return ('process_call', p.NAME)
@_('var_assign')
def statement(self, p):
return p.var_assign
@_('BOX NAME "=" expr')
def var_assign(self, p):
return ('var_assign', p.NAME, p.expr)
@_('BOX NAME "=" STRING')
def var_assign(self, p):
return ('var_assign', p.NAME, p.STRING)
@_('NAME "=" expr')
def var_assign(self, p):
return ('var_assign', p.NAME, p.expr)
@_('NAME "=" STRING')
def var_assign(self, p):
return ('var_assign', p.NAME, p.STRING)
@_('expr')
def statement(self, p):
return (p.expr)
@_('expr "+" expr')
def expr(self, p):
return ('add', p.expr0, p.expr1)
@_('expr "-" expr')
def expr(self, p):
return ('sub', p.expr0, p.expr1)
@_('expr "*" expr')
def expr(self, p):
return ('mul', p.expr0, p.expr1)
@_('expr "/" expr')
def expr(self, p):
return ('div', p.expr0, p.expr1)
@_('"-" expr %prec UMINUS')
def expr(self, p):
return p.expr
@_('NAME')
def expr(self, p):
return ('var', p.NAME)
@_('NUMBER')
def expr(self, p):
return ('num', p.NUMBER)
Execute File
from lexer import BasicLexer
from parser_ import BasicParser
class BasicExecute:
def __init__(self, tree, env):
self.env = env
result = self.walkTree(tree)
if result is not None and isinstance(result, int):
print(result)
if isinstance(result, str) and result[0] == '"':
print(result)
def walkTree(self, node):
if isinstance(node, int):
return node
if isinstance(node, str):
return node
if node is None:
return None
if node[0] == 'program':
if node[1] == None:
self.walkTree(node[2])
else:
self.walkTree(node[1])
self.walkTree(node[2])
if node[0] == 'num':
return node[1]
if node[0] == 'str':
return node[1]
if node[0] == 'process_def':
self.env[node[1]] = node[2]
if node[0] == 'process_call':
try:
return self.walkTree(self.env[node[1]])
except LookupError:
print("Undefined function '%s'" % node[1])
return 0
if node[0] == 'add':
return self.walkTree(node[1]) + self.walkTree(node[2])
elif node[0] == 'sub':
return self.walkTree(node[1]) - self.walkTree(node[2])
elif node[0] == 'mul':
return self.walkTree(node[1]) * self.walkTree(node[2])
elif node[0] == 'div':
return self.walkTree(node[1]) / self.walkTree(node[2])
if node[0] == 'var_assign':
self.env[node[1]] = self.walkTree(node[2])
return node[1]
if node[0] == 'var':
try:
return self.env[node[1]]
except LookupError:
print("Undefined variable '" + node[1] + "' found!")
return 0
if __name__ == '__main__':
lexer = BasicLexer()
parser = BasicParser()
env = {}
while True:
try:
text = input('joho > ')
except EOFError:
break
if text:
tree = parser.parse(lexer.tokenize(text))
BasicExecute(tree, env)
Aucun commentaire:
Enregistrer un commentaire