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 No valediction
\item Unexpected token \item Unexpected token
\item Random compiler error \item Random compiler error
\item Unknown builtin
\item Wrong number of arguments for 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{enumerate}
\end{document} \end{document}

View File

@ -1,8 +1,8 @@
hello| hello|
$do random<1;128;> -> n| set do random<1;128;> -> n|
$0 -> guess| set 0 -> guess|
until variable guess = variable n [ 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 high';> if variable guess > variable n|
do print<'too low';> if variable guess < variable n| do print<'too low';> if variable guess < variable n|
do print<'correct!';> 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 from rply.token import BaseBox
BUILTIN_ARGS = {
"print": "*",
"input" : "*",
"random": 2
}
def rep_join(l): def rep_join(l):
format_string = ',\n'.join( format_string = ',\n'.join(
[repr(i) if not isinstance(i, str) else i for i in l] [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" format_string = f"\n {format_string}\n"
return format_string return format_string
class Exp(BaseBox): class Exp(BaseBox):
def eval(self, vtable, ftable): def eval(self, vtable, ftable):
return vtable, ftable, None return vtable, ftable, None
@ -86,8 +92,7 @@ class ExpABinop(Exp):
elif self.op == "<": elif self.op == "<":
return vtable, ftable, r1 < r2 return vtable, ftable, r1 < r2
else: else:
print(f"E007: Unknown binop {self.op}") raise Exception(f"Unknown binop {self.op}")
exit()
class ExpList(Exp): class ExpList(Exp):
def __init__(self, expressions: list[Exp]): def __init__(self, expressions: list[Exp]):
@ -143,9 +148,15 @@ class Command(BaseBox):
return f"command()" return f"command()"
class Builtin(Command): class Builtin(Command):
def __init__(self, builtin: str, args: list[Exp]): def __init__(self, builtin, args: list[Exp]):
self.builtin = builtin self.builtin = builtin.value
self.args = args 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: def __repr__(self) -> str:
return f"builtin({self.builtin}, {self.args})" return f"builtin({self.builtin}, {self.args})"
@ -174,10 +185,6 @@ class Builtin(Command):
result = input() result = input()
return vtable, ftable, result return vtable, ftable, result
elif self.builtin == "random": 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, r1 = self.args[0].eval(vtable, ftable)
vtable, ftable, r2 = self.args[1].eval(vtable, ftable) vtable, ftable, r2 = self.args[1].eval(vtable, ftable)
@ -185,7 +192,7 @@ class Builtin(Command):
return vtable, ftable, r return vtable, ftable, r
else: else:
raise Exception(f"E005: Unknown builtin {self.builtin}") raise Exception(f"Unknown builtin {self.builtin}")
class Do(BaseBox): class Do(BaseBox):
def __init__(self, command: Command): def __init__(self, command: Command):
@ -309,6 +316,22 @@ class StatementIf(Statement):
else: else:
return vtable, ftable, result 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): class StatementUntil(Statement):
def __init__(self, statement: Statement, condition): def __init__(self, statement: Statement, condition):
self.statement = statement self.statement = statement

View File

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

View File

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

0
test.sh Normal file → Executable file
View File

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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