This commit is contained in:
2024-02-21 14:01:22 +01:00
parent e8dfb94860
commit b6949f6a73
22 changed files with 88 additions and 43 deletions

Binary file not shown.

View File

@ -47,8 +47,9 @@
\item No valediction
\item Unexpected token
\item Random compiler error
\item Unknown builtin
\item Wrong number of arguments for builtin
\item Unknown binop
\end{enumerate}
\begin{enumerate}[label={\textbf{C\protect\threedigits{\theenumi}:}}, leftmargin = *]
\item Because assertion incorrect
\end{enumerate}
\end{document}

View File

@ -1,8 +1,8 @@
hello|
$do random<1;128;> -> n|
$0 -> guess|
set do random<1;128;> -> n|
set 0 -> guess|
until variable guess = variable n [
$do input<'guess: ';> -> guess|
set do input<'guess: ';> -> guess|
do print<'too high';> if variable guess > variable n|
do print<'too low';> if variable guess < variable n|
do print<'correct!';> if variable guess = variable n|

View File

@ -2,6 +2,13 @@ import random
from rply.token import BaseBox
BUILTIN_ARGS = {
"print": "*",
"input" : "*",
"random": 2
}
def rep_join(l):
format_string = ',\n'.join(
[repr(i) if not isinstance(i, str) else i for i in l]
@ -11,7 +18,6 @@ def rep_join(l):
format_string = f"\n {format_string}\n"
return format_string
class Exp(BaseBox):
def eval(self, vtable, ftable):
return vtable, ftable, None
@ -86,8 +92,7 @@ class ExpABinop(Exp):
elif self.op == "<":
return vtable, ftable, r1 < r2
else:
print(f"E007: Unknown binop {self.op}")
exit()
raise Exception(f"Unknown binop {self.op}")
class ExpList(Exp):
def __init__(self, expressions: list[Exp]):
@ -143,9 +148,15 @@ class Command(BaseBox):
return f"command()"
class Builtin(Command):
def __init__(self, builtin: str, args: list[Exp]):
self.builtin = builtin
def __init__(self, builtin, args: list[Exp]):
self.builtin = builtin.value
self.args = args
self.position = builtin.source_pos.lineno
expected_args = BUILTIN_ARGS[self.builtin]
if not (expected_args == "*" or expected_args == len(self.args)):
print(f"E005: Wrong number of arguments for builtin '{self.builtin}' ({len(self.args)}) at line {self.position}")
exit()
def __repr__(self) -> str:
return f"builtin({self.builtin}, {self.args})"
@ -174,10 +185,6 @@ class Builtin(Command):
result = input()
return vtable, ftable, result
elif self.builtin == "random":
if not len(self.args) == 2:
print(f"E006: Wrong number of arguments for builtin '{self.builtin}' ({len(self.args)})")
exit()
vtable, ftable, r1 = self.args[0].eval(vtable, ftable)
vtable, ftable, r2 = self.args[1].eval(vtable, ftable)
@ -185,7 +192,7 @@ class Builtin(Command):
return vtable, ftable, r
else:
raise Exception(f"E005: Unknown builtin {self.builtin}")
raise Exception(f"Unknown builtin {self.builtin}")
class Do(BaseBox):
def __init__(self, command: Command):
@ -309,6 +316,22 @@ class StatementIf(Statement):
else:
return vtable, ftable, result
class StatementBecause(Statement):
def __init__(self, statement: Statement, condition):
self.statement = statement
self.condition = condition
def __repr__(self) -> str:
return f"if({self.statement}, {self.condition})"
def eval(self, vtable, ftable):
vtable, ftable, result = self.condition.eval(vtable, ftable)
if result:
return self.statement.eval(vtable, ftable)
else:
print("C001: Because assertion incorrect")
exit()
class StatementUntil(Statement):
def __init__(self, statement: Statement, condition):
self.statement = statement

View File

@ -9,13 +9,14 @@ KEYWORD_TOKENS = [("KEYWORD_"+i.upper(), i) for i in [
"maybe",
"do",
"if",
# "because",
"because",
"until",
"define",
"as",
"variable",
"return",
"argument"
"argument",
"set"
]]
BUILTIN_TOKENS = [("BUILTIN", i) for i in [
@ -50,7 +51,7 @@ SYMBOL_TOKENS = [
("SYMBOL_LT", r"\<"),
("SYMBOL_GT", r"\>"),
("SYMBOL_EQUALS", r"\="),
("SYMBOL_DOLLAR", r"\$")
# ("SYMBOL_DOLLAR", r"\$")
]
ALL_TOKENS = (

View File

@ -9,9 +9,9 @@ class Parser():
[i[0] for i in ALL_TOKENS],
precedence=[
('left', ["KEYWORD_MAYBE", "KEYWORD_RETURN"]),
('left', ["KEYWORD_IF", "KEYWORD_UNTIL", "KEYWORD_DEFINE", "KEYWORD_AS"]),
('left', ["KEYWORD_DO", "BUILTIN"]),
('left', ["SYMBOL_EQUALS", "SYMBOL_SET"]),
('left', ["KEYWORD_IF", "KEYWORD_BECAUSE", "KEYWORD_UNTIL", "KEYWORD_DEFINE", "KEYWORD_AS"]),
('left', ["KEYWORD_DO", "BUILTIN", "SYMBOL_SET"]),
('left', ["SYMBOL_EQUALS"]),
('left', ["SYMBOL_PLUS", "SYMBOL_MINUS"]),
('left', ["SYMBOL_TIMES", "SYMBOL_DIVIDE", "SYMBOL_LT","SYMBOL_GT"])
]
@ -33,7 +33,7 @@ class Parser():
return [tokens[0]] + tokens[2]
## statement ##
@self.pg.production('statement : SYMBOL_DOLLAR expression SYMBOL_SET ID', precedence="SYMBOL_SET")
@self.pg.production('statement : KEYWORD_SET expression SYMBOL_SET ID', precedence="SYMBOL_SET")
def statement_set(tokens):
return ast_nodes.StatementSet(tokens[1], tokens[3].value)
@ -49,6 +49,10 @@ class Parser():
def statement_if(tokens):
return ast_nodes.StatementIf(tokens[0], tokens[2])
@self.pg.production('statement : statement KEYWORD_BECAUSE expression')
def statement_because(tokens):
return ast_nodes.StatementBecause(tokens[0], tokens[2])
@self.pg.production('statement : KEYWORD_UNTIL expression statement')
def statement_until(tokens):
return ast_nodes.StatementUntil(tokens[2],tokens[1])
@ -68,7 +72,7 @@ class Parser():
## command ##
@self.pg.production('command : BUILTIN SYMBOL_LT expressions SYMBOL_GT')
def command_builtin(tokens):
return ast_nodes.Builtin(tokens[0].value, tokens[2])
return ast_nodes.Builtin(tokens[0], tokens[2])
@self.pg.production('command : SYMBOL_QUOTE ID SYMBOL_QUOTE SYMBOL_LT expressions SYMBOL_GT')
def command_call(tokens):
@ -89,7 +93,7 @@ class Parser():
return ast_nodes.ExpInt(int(tokens[0].value))
@self.pg.production('expression : DATA_FLOAT')
def exp_int(tokens):
def exp_float(tokens):
return ast_nodes.ExpInt(float(tokens[0].value))
@self.pg.production('expression : DATA_STRING')

0
test.sh Normal file → Executable file
View File

View File

@ -1,4 +1,4 @@
hello|
$2 -> x|
set 2 -> x|
do print<variable x;>|
goodbye|

View File

@ -1,10 +1,10 @@
hello|
$1 -> x|
$2 -> y|
$5 -> z|
$variable x+variable y -> z| // 3
$5-variable z -> z| // 2
$2*variable z -> x| // 4
$variable x/variable y -> y| // 2
set 1 -> x|
set 2 -> y|
set 5 -> z|
set variable x+variable y -> z| // 3
set 5-variable z -> z| // 2
set 2*variable z -> x| // 4
set variable x/variable y -> y| // 2
do print<variable x;variable y;variable z;>|
goodbye|

View File

@ -1,6 +1,6 @@
hello|
[
$5 -> x|
set 5 -> x|
do print<variable x;>|
]|
goodbye|

View File

@ -1,5 +1,5 @@
hello|
$1 -> x|
maybe $variable x + 1 -> x|
set 1 -> x|
maybe set variable x + 1 -> x|
do print<variable x;>|
goodbye|

View File

@ -1,5 +1,5 @@
hello|
$2 -> x|
set 2 -> x|
do print<'a';> if variable x = 1|
do print<'b';> if variable x = 2|
goodbye|

View File

@ -1,8 +1,8 @@
hello|
$ 1 + 2 * 3 -> x|
set 1 + 2 * 3 -> x|
do print<variable x;>|
$ 5 -> y if variable x = 7|
set 5 -> y if variable x = 7|
do print<variable y;>|
$$5 -> z + 1 -> a|
set set 5 -> z + 1 -> a|
do print<variable z; variable a;>|
goodbye|

View File

@ -1,2 +1,2 @@
$2 -> x|
set 2 -> x|
goodbye|

View File

@ -1,2 +1,2 @@
hello|
$2 -> x|
set 2 -> x|

View File

@ -1,6 +1,6 @@
hello|
${1;2;3;} -> x|
set {1;2;3;} -> x|
do print<variable x;>|
${1;1+1;do print<3;>;} -> y|
set {1;1+1;do print<3;>;} -> y|
do print<variable y{5 - 4};>|
goodbye|

View File

@ -0,0 +1 @@
3

5
tests/13_because.plthy Normal file
View File

@ -0,0 +1,5 @@
hello|
set 2 -> x|
set 3 -> x because variable x = 2|
do print<variable x;>|
goodbye|

View File

@ -0,0 +1 @@
E005: Wrong number of arguments for builtin 'random' (1) at line 2

View File

@ -0,0 +1,3 @@
hello|
do random<2;>|
goodbye|

1
tests/15_C001.expected Normal file
View File

@ -0,0 +1 @@
C001: Because assertion incorrect

5
tests/15_C001.plthy Normal file
View File

@ -0,0 +1,5 @@
hello|
set 2 -> x|
set 3 -> x because variable x = 3|
do print<variable x;>|
goodbye|