✨
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 {
|
} 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
|
||||||
}
|
}
|
||||||
|
|||||||
67
ast_nodes.py
67
ast_nodes.py
@@ -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)
|
||||||
|
|||||||
1
lexer.py
1
lexer.py
@@ -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
24
main.py
@@ -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()
|
||||||
|
|||||||
32
parser.py
32
parser.py
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user