This commit is contained in:
NikolajDanger
2022-06-08 13:08:19 +02:00
parent 2dfbb33213
commit 912c46ab7c
5 changed files with 121 additions and 19 deletions

View File

@@ -19,7 +19,7 @@ DEFINI fib x UT {
} ALUID SI x EST I TUNC { } ALUID SI x EST I TUNC {
REDI I REDI I
} ALUID { } ALUID {
REDI (INVOCA fib (x-II) + INVOCA fib (x-I)) REDI ((INVOCA fib (x-II)) + (INVOCA fib (x-I)))
} }
} }
``` ```
@@ -30,13 +30,13 @@ DEFINI fib x UT {
VOCA FORS VOCA FORS
DESIGNA correct UT FORTIS_NUMERUS I C DESIGNA correct UT FORTIS_NUMERUS I C
DESIGNA guess UT NULLUS DESIGNA gvess UT NULLUS
DUM FALSITAS FACE { DUM FALSITAS FACE {
DESIGNA guess UT AUDI_NUMERUS DESIGNA gvess UT AUDI_NUMERUS
SI guess MINUS correct TUNC { SI gvess MINUS correct TUNC {
DICE "Too low!" DICE "Too low!"
} ALUID SI guess PLUS correct TUNC { } ALUID SI gvess PLUS correct TUNC {
DICE "Too high!" DICE "Too high!"
} ALUID { } ALUID {
ERUMPE ERUMPE
@@ -170,8 +170,8 @@ SI x ET y TUNC {
### DONICUM loops ### DONICUM loops
``` ```
DESIGNA x UT NULLUM DESIGNA x UT NULLUS
DONICUM y UT NULLUM USQUE X FACE { DONICUM y UT NULLUS USQUE X FACE {
DESIGNA x UT x + y DESIGNA x UT x + y
} }
DICE x DICE x
@@ -181,7 +181,7 @@ DICE x
### DUM loops ### DUM loops
``` ```
DESIGNA x UT NULLUM DESIGNA x UT NULLUS
DUM x PLUS X FACE { DUM x PLUS X FACE {
DESIGNA x UT x+I DESIGNA x UT x+I
} }

View File

@@ -23,6 +23,7 @@ def rep_join(l):
return format_string return format_string
# TODO: Magnum
def num_to_int(n): def num_to_int(n):
return roman.fromRoman(n) return roman.fromRoman(n)
@@ -31,6 +32,8 @@ def make_string(n):
return n return n
elif isinstance(n, int): elif isinstance(n, int):
return roman.toRoman(n) return roman.toRoman(n)
elif isinstance(n, list):
return f"[{' '.join([make_string(i) for i in n])}]"
else: else:
raise Exception(n) raise Exception(n)
@@ -45,6 +48,31 @@ class ExpressionStatement(BaseBox):
self.expression.eval(vtable.copy(), ftable.copy(), modules) self.expression.eval(vtable.copy(), ftable.copy(), modules)
return vtable, ftable return vtable, ftable
class DataArray(BaseBox):
def __init__(self, content) -> None:
self.content = content
def __repr__(self) -> str:
content_string = rep_join(self.content)
return f"Array([{content_string}])"
def eval(self, vtable, ftable, modules):
content = [i.eval(vtable, ftable, modules) for i in self.content]
return content
class DataRangeArray(BaseBox):
def __init__(self, from_value, to_value) -> None:
self.from_value = from_value
self.to_value = to_value
def __repr__(self) -> str:
content_string = rep_join([self.from_value, self.to_value])
return f"RangeArray([{content_string}])"
def eval(self, vtable, ftable, modules):
content = list(range(self.from_value.eval(), self.to_value.eval()))
return content
class String(BaseBox): class String(BaseBox):
def __init__(self, value) -> None: def __init__(self, value) -> None:
self.value = value self.value = value
@@ -122,7 +150,7 @@ class Defini(BaseBox):
) )
return f"Defini({def_string})" return f"Defini({def_string})"
def eval(self, vtable, ftable, modules): def eval(self, vtable, ftable, _):
ftable[self.name.name] = ( ftable[self.name.name] = (
self.parameters, self.statements self.parameters, self.statements
) )
@@ -180,6 +208,11 @@ class BinOp(BaseBox):
return left + right return left + right
case "SYMBOL_MINUS": case "SYMBOL_MINUS":
return left - right return left - right
case "SYMBOL_TIMES":
return left * right
case "SYMBOL_DIVIDE":
# TODO: Fractio
return left // right
case "KEYWORD_MINUS": case "KEYWORD_MINUS":
return left < right return left < right
case "KEYWORD_PLUS": case "KEYWORD_PLUS":
@@ -242,6 +275,37 @@ class DumStatement(BaseBox):
return vtable, ftable return vtable, ftable
class PerStatement(BaseBox):
def __init__(self, data_list, variable_name, statements) -> None:
self.data_list = data_list
self.variable_name = variable_name
self.statements = statements
def __repr__(self) -> str:
test = repr(self.data_list)
variable_name = repr(self.variable_name)
statements = f"statements([{rep_join(self.statements)}])"
dum_string = rep_join([test, variable_name, statements])
return f"Per({dum_string})"
def eval(self, vtable, ftable, modules):
data_array = self.data_list.eval(vtable, ftable, modules)
variable_name = self.variable_name.name
for i in data_array:
vtable[variable_name] = i
for statement in self.statements:
vtable, ftable = statement.eval(
vtable, ftable, modules
)
if vtable["ERUMPE"]:
break
if vtable["ERUMPE"]:
vtable["ERUMPE"] = False
break
return vtable, ftable
class Invoca(BaseBox): class Invoca(BaseBox):
def __init__(self, name, parameters) -> None: def __init__(self, name, parameters) -> None:
self.name = name self.name = name
@@ -294,6 +358,7 @@ class BuiltIn(BaseBox):
vtable["ERUMPE"] = True vtable["ERUMPE"] = True
return None return None
case "FORTIS_NUMERUS": case "FORTIS_NUMERUS":
# TODO: Fors
return random.randint(parameters[0], parameters[1]) return random.randint(parameters[0], parameters[1])
case _: case _:
raise Exception(self.builtin) raise Exception(self.builtin)

View File

@@ -13,6 +13,7 @@ keyword_tokens = [("KEYWORD_"+i, i) for i in [
"FACE", "FACE",
"FALSITAS", "FALSITAS",
"INVOCA", "INVOCA",
"IN",
"MINUS", "MINUS",
"NULLUS", "NULLUS",
"PER", "PER",

24
main.py
View File

@@ -2,18 +2,23 @@ from lexer import Lexer
from parser import Parser from parser import Parser
text_input = """ text_input = """
DEFINI fib x UT { VOCA FORS
SI x EST NULLUS TUNC {
REDI NULLUS DESIGNA correct UT FORTIS_NUMERUS I C
} ALUID SI x EST I TUNC { DESIGNA gvess UT NULLUS
REDI I
DUM FALSITAS FACE {
DESIGNA gvess UT AUDI_NUMERUS
SI gvess MINUS correct TUNC {
DICE "Too low!"
} ALUID SI gvess PLUS correct TUNC {
DICE "Too high!"
} ALUID { } ALUID {
REDI ((INVOCA fib (x-II)) + (INVOCA fib (x-I))) ERUMPE
} }
} }
DICE "Input n:" DICE "You guessed correctly!"
DICE (INVOCA fib AUDI_NUMERUS)
""" """
lexer = Lexer().get_lexer() lexer = Lexer().get_lexer()
@@ -22,6 +27,9 @@ pg.parse()
parser = pg.get_parser() parser = pg.get_parser()
tokens = lexer.lex(text_input) tokens = lexer.lex(text_input)
#for token in tokens:
# print(token)
x = parser.parse(tokens) x = parser.parse(tokens)
#print(x)
x.eval() x.eval()

View File

@@ -1,3 +1,4 @@
from multiprocessing.dummy import Array
from rply import ParserGenerator from rply import ParserGenerator
from lexer import all_tokens from lexer import all_tokens
@@ -7,7 +8,13 @@ ALL_TOKENS = list(set([i[0] for i in all_tokens]))
class Parser(): class Parser():
def __init__(self): def __init__(self):
self.pg = ParserGenerator(ALL_TOKENS) self.pg = ParserGenerator(
ALL_TOKENS,
precedence=[
('left', ["SYMBOL_PLUS", "SYMBOL_MINUS"]),
('left', ["SYMBOL_TIMES", "SYMBOL_DIVIDE"])
]
)
def parse(self): def parse(self):
@self.pg.production('program : opt_newline module_calls statements') @self.pg.production('program : opt_newline module_calls statements')
@@ -94,6 +101,8 @@ class Parser():
@self.pg.production('expression : expression SYMBOL_MINUS expression') @self.pg.production('expression : expression SYMBOL_MINUS expression')
@self.pg.production('expression : expression SYMBOL_PLUS expression') @self.pg.production('expression : expression SYMBOL_PLUS expression')
@self.pg.production('expression : expression SYMBOL_TIMES expression')
@self.pg.production('expression : expression SYMBOL_DIVIDE expression')
@self.pg.production('expression : expression KEYWORD_EST expression') @self.pg.production('expression : expression KEYWORD_EST expression')
@self.pg.production('expression : expression KEYWORD_MINUS expression') @self.pg.production('expression : expression KEYWORD_MINUS expression')
@self.pg.production('expression : expression KEYWORD_PLUS expression') @self.pg.production('expression : expression KEYWORD_PLUS expression')
@@ -116,8 +125,10 @@ class Parser():
def si_statement(tokens): def si_statement(tokens):
return tokens[0] return tokens[0]
@self.pg.production('statement : per_statement')
@self.pg.production('statement : dum_statement') @self.pg.production('statement : dum_statement')
def dum_statement(tokens): @self.pg.production('statement : donicum_statement')
def loops(tokens):
return tokens[0] return tokens[0]
@self.pg.production('statement : KEYWORD_ERUMPE') @self.pg.production('statement : KEYWORD_ERUMPE')
@@ -132,6 +143,15 @@ class Parser():
def dum(tokens): def dum(tokens):
return ast_nodes.DumStatement(tokens[1], tokens[5]) return ast_nodes.DumStatement(tokens[1], tokens[5])
@self.pg.production('per_statement : KEYWORD_PER id KEYWORD_IN expression KEYWORD_FACE SYMBOL_LCURL opt_newline statements opt_newline SYMBOL_RCURL')
def per(tokens):
return ast_nodes.PerStatement(tokens[3], tokens[1], tokens[7])
@self.pg.production('donicum_statement : KEYWORD_DONICUM id KEYWORD_UT expression KEYWORD_USQUE expression KEYWORD_FACE SYMBOL_LCURL opt_newline statements opt_newline SYMBOL_RCURL')
def donicum(tokens):
range_array = ast_nodes.DataRangeArray(tokens[3], tokens[5])
return ast_nodes.PerStatement(range_array, tokens[1], tokens[9])
@self.pg.production('aluid_statement : ') @self.pg.production('aluid_statement : ')
def aluid_empty(_): def aluid_empty(_):
return None return None
@@ -148,6 +168,14 @@ class Parser():
def parens(tokens): def parens(tokens):
return tokens[1] return tokens[1]
@self.pg.production('expression : SYMBOL_LBRACKET expressions SYMBOL_RBRACKET')
def array(tokens):
return ast_nodes.DataArray(tokens[1])
@self.pg.production('expression : SYMBOL_LBRACKET expression KEYWORD_USQUE expression SYMBOL_RBRACKET')
def range_array(tokens):
return ast_nodes.DataRangeArray(tokens[1], tokens[3])
@self.pg.error @self.pg.error
def error_handle(token): def error_handle(token):
raise ValueError(token) raise ValueError(token)