✨
This commit is contained in:
16
README.md
16
README.md
@@ -19,7 +19,7 @@ DEFINI fib x UT {
|
||||
} ALUID SI x EST I TUNC {
|
||||
REDI I
|
||||
} 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
|
||||
|
||||
DESIGNA correct UT FORTIS_NUMERUS I C
|
||||
DESIGNA guess UT NULLUS
|
||||
DESIGNA gvess UT NULLUS
|
||||
|
||||
DUM FALSITAS FACE {
|
||||
DESIGNA guess UT AUDI_NUMERUS
|
||||
SI guess MINUS correct TUNC {
|
||||
DESIGNA gvess UT AUDI_NUMERUS
|
||||
SI gvess MINUS correct TUNC {
|
||||
DICE "Too low!"
|
||||
} ALUID SI guess PLUS correct TUNC {
|
||||
} ALUID SI gvess PLUS correct TUNC {
|
||||
DICE "Too high!"
|
||||
} ALUID {
|
||||
ERUMPE
|
||||
@@ -170,8 +170,8 @@ SI x ET y TUNC {
|
||||
### DONICUM loops
|
||||
|
||||
```
|
||||
DESIGNA x UT NULLUM
|
||||
DONICUM y UT NULLUM USQUE X FACE {
|
||||
DESIGNA x UT NULLUS
|
||||
DONICUM y UT NULLUS USQUE X FACE {
|
||||
DESIGNA x UT x + y
|
||||
}
|
||||
DICE x
|
||||
@@ -181,7 +181,7 @@ DICE x
|
||||
|
||||
### DUM loops
|
||||
```
|
||||
DESIGNA x UT NULLUM
|
||||
DESIGNA x UT NULLUS
|
||||
DUM x PLUS X FACE {
|
||||
DESIGNA x UT x+I
|
||||
}
|
||||
|
||||
67
ast_nodes.py
67
ast_nodes.py
@@ -23,6 +23,7 @@ def rep_join(l):
|
||||
|
||||
return format_string
|
||||
|
||||
# TODO: Magnum
|
||||
def num_to_int(n):
|
||||
return roman.fromRoman(n)
|
||||
|
||||
@@ -31,6 +32,8 @@ def make_string(n):
|
||||
return n
|
||||
elif isinstance(n, int):
|
||||
return roman.toRoman(n)
|
||||
elif isinstance(n, list):
|
||||
return f"[{' '.join([make_string(i) for i in n])}]"
|
||||
else:
|
||||
raise Exception(n)
|
||||
|
||||
@@ -45,6 +48,31 @@ class ExpressionStatement(BaseBox):
|
||||
self.expression.eval(vtable.copy(), ftable.copy(), modules)
|
||||
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):
|
||||
def __init__(self, value) -> None:
|
||||
self.value = value
|
||||
@@ -122,7 +150,7 @@ class Defini(BaseBox):
|
||||
)
|
||||
return f"Defini({def_string})"
|
||||
|
||||
def eval(self, vtable, ftable, modules):
|
||||
def eval(self, vtable, ftable, _):
|
||||
ftable[self.name.name] = (
|
||||
self.parameters, self.statements
|
||||
)
|
||||
@@ -180,6 +208,11 @@ class BinOp(BaseBox):
|
||||
return left + right
|
||||
case "SYMBOL_MINUS":
|
||||
return left - right
|
||||
case "SYMBOL_TIMES":
|
||||
return left * right
|
||||
case "SYMBOL_DIVIDE":
|
||||
# TODO: Fractio
|
||||
return left // right
|
||||
case "KEYWORD_MINUS":
|
||||
return left < right
|
||||
case "KEYWORD_PLUS":
|
||||
@@ -242,6 +275,37 @@ class DumStatement(BaseBox):
|
||||
|
||||
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):
|
||||
def __init__(self, name, parameters) -> None:
|
||||
self.name = name
|
||||
@@ -294,6 +358,7 @@ class BuiltIn(BaseBox):
|
||||
vtable["ERUMPE"] = True
|
||||
return None
|
||||
case "FORTIS_NUMERUS":
|
||||
# TODO: Fors
|
||||
return random.randint(parameters[0], parameters[1])
|
||||
case _:
|
||||
raise Exception(self.builtin)
|
||||
|
||||
1
lexer.py
1
lexer.py
@@ -13,6 +13,7 @@ keyword_tokens = [("KEYWORD_"+i, i) for i in [
|
||||
"FACE",
|
||||
"FALSITAS",
|
||||
"INVOCA",
|
||||
"IN",
|
||||
"MINUS",
|
||||
"NULLUS",
|
||||
"PER",
|
||||
|
||||
24
main.py
24
main.py
@@ -2,18 +2,23 @@ from lexer import Lexer
|
||||
from parser import Parser
|
||||
|
||||
text_input = """
|
||||
DEFINI fib x UT {
|
||||
SI x EST NULLUS TUNC {
|
||||
REDI NULLUS
|
||||
} ALUID SI x EST I TUNC {
|
||||
REDI I
|
||||
VOCA FORS
|
||||
|
||||
DESIGNA correct UT FORTIS_NUMERUS I C
|
||||
DESIGNA gvess UT NULLUS
|
||||
|
||||
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 {
|
||||
REDI ((INVOCA fib (x-II)) + (INVOCA fib (x-I)))
|
||||
ERUMPE
|
||||
}
|
||||
}
|
||||
|
||||
DICE "Input n:"
|
||||
DICE (INVOCA fib AUDI_NUMERUS)
|
||||
DICE "You guessed correctly!"
|
||||
"""
|
||||
|
||||
lexer = Lexer().get_lexer()
|
||||
@@ -22,6 +27,9 @@ pg.parse()
|
||||
parser = pg.get_parser()
|
||||
|
||||
tokens = lexer.lex(text_input)
|
||||
#for token in tokens:
|
||||
# print(token)
|
||||
|
||||
x = parser.parse(tokens)
|
||||
#print(x)
|
||||
x.eval()
|
||||
|
||||
32
parser.py
32
parser.py
@@ -1,3 +1,4 @@
|
||||
from multiprocessing.dummy import Array
|
||||
from rply import ParserGenerator
|
||||
|
||||
from lexer import all_tokens
|
||||
@@ -7,7 +8,13 @@ ALL_TOKENS = list(set([i[0] for i in all_tokens]))
|
||||
|
||||
class Parser():
|
||||
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):
|
||||
@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_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_MINUS expression')
|
||||
@self.pg.production('expression : expression KEYWORD_PLUS expression')
|
||||
@@ -116,8 +125,10 @@ class Parser():
|
||||
def si_statement(tokens):
|
||||
return tokens[0]
|
||||
|
||||
@self.pg.production('statement : per_statement')
|
||||
@self.pg.production('statement : dum_statement')
|
||||
def dum_statement(tokens):
|
||||
@self.pg.production('statement : donicum_statement')
|
||||
def loops(tokens):
|
||||
return tokens[0]
|
||||
|
||||
@self.pg.production('statement : KEYWORD_ERUMPE')
|
||||
@@ -132,6 +143,15 @@ class Parser():
|
||||
def dum(tokens):
|
||||
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 : ')
|
||||
def aluid_empty(_):
|
||||
return None
|
||||
@@ -148,6 +168,14 @@ class Parser():
|
||||
def parens(tokens):
|
||||
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
|
||||
def error_handle(token):
|
||||
raise ValueError(token)
|
||||
|
||||
Reference in New Issue
Block a user