mirror of
https://github.com/irmen/prog8.git
synced 2024-12-23 09:32:43 +00:00
endl parsing
This commit is contained in:
parent
d92f91f22f
commit
d9c62c2149
3
.gitignore
vendored
3
.gitignore
vendored
@ -14,3 +14,6 @@
|
||||
*.asm
|
||||
*.labels.txt
|
||||
.mypy_cache/
|
||||
__pycache__/
|
||||
parser.out
|
||||
parsetab.py
|
||||
|
@ -9,20 +9,17 @@ tokens = (
|
||||
"FLOATINGPOINT",
|
||||
"DOTTEDNAME",
|
||||
"NAME",
|
||||
"DOT",
|
||||
"IS",
|
||||
"CLOBBEREDREGISTER",
|
||||
"REGISTER",
|
||||
"COMMENT",
|
||||
"DIRECTIVE",
|
||||
"AUGASSIGN",
|
||||
"EQUAL",
|
||||
"NOTEQUAL",
|
||||
"EQUALS",
|
||||
"NOTEQUALS",
|
||||
"RARROW",
|
||||
"RETURN",
|
||||
"TILDE",
|
||||
"VARTYPE",
|
||||
"KEYWORD",
|
||||
"SUB",
|
||||
"DATATYPE",
|
||||
"CHARACTER",
|
||||
@ -31,37 +28,47 @@ tokens = (
|
||||
"GOTO",
|
||||
"INCR",
|
||||
"DECR",
|
||||
"NOT",
|
||||
"LT",
|
||||
"GT",
|
||||
"LE",
|
||||
"GE",
|
||||
"BITAND",
|
||||
"BITOR",
|
||||
"BITXOR",
|
||||
"BITINVERT",
|
||||
"LOGICAND",
|
||||
"LOGICOR",
|
||||
"LOGICNOT",
|
||||
"POWER",
|
||||
"LABEL",
|
||||
"IF",
|
||||
"ADDRESSOF",
|
||||
"PRESERVEREGS",
|
||||
"INLINEASM",
|
||||
"ENDL"
|
||||
)
|
||||
|
||||
literals = ['+', '-', '*', '/', '(', ')', '[', ']', '{', '}', '.', ',', '!', '?', ':']
|
||||
|
||||
# regex rules for simple tokens
|
||||
|
||||
t_ADDRESSOF = r"\#"
|
||||
t_BITAND = r"&"
|
||||
t_BITOR = r"\|"
|
||||
t_BITXOR = r"\^"
|
||||
t_BITINVERT = r"~"
|
||||
t_IS = r"="
|
||||
t_TILDE = r"~"
|
||||
t_DIRECTIVE = r"%[a-z]+"
|
||||
t_AUGASSIGN = r"\+=|-=|/=|\*=|<<=|>>=|&=|\|=|\^="
|
||||
t_DECR = r"--"
|
||||
t_INCR = r"\+\+"
|
||||
t_EQUAL = r"=="
|
||||
t_NOTEQUAL = r"!="
|
||||
t_EQUALS = r"=="
|
||||
t_NOTEQUALS = r"!="
|
||||
t_LT = r"<"
|
||||
t_GT = r">"
|
||||
t_LE = r"<="
|
||||
t_GE = r">="
|
||||
t_IF = "if(_[a-z]+)?"
|
||||
t_RARROW = r"->"
|
||||
t_POWER = r"\*\*"
|
||||
|
||||
|
||||
# ignore inline whitespace
|
||||
t_ignore = " \t"
|
||||
@ -83,7 +90,9 @@ reserved = {
|
||||
"return": "RETURN",
|
||||
"true": "BOOLEAN",
|
||||
"false": "BOOLEAN",
|
||||
"not": "NOT",
|
||||
"not": "LOGICNOT",
|
||||
"and": "LOGICAND",
|
||||
"or": "LOGICOR",
|
||||
"AX": "REGISTER",
|
||||
"AY": "REGISTER",
|
||||
"XY": "REGISTER",
|
||||
@ -96,12 +105,15 @@ reserved = {
|
||||
"if": "IF",
|
||||
"if_true": "IF",
|
||||
"if_not": "IF",
|
||||
"if_zero": "IF",
|
||||
"if_ne": "IF",
|
||||
"if_eq": "IF",
|
||||
"if_cc": "IF",
|
||||
"if_cs": "IF",
|
||||
"if_vc": "IF",
|
||||
"if_vs": "IF",
|
||||
"if_ge": "IF",
|
||||
"if_le": "IF",
|
||||
"if_gt": "IF",
|
||||
"if_lt": "IF",
|
||||
"if_pos": "IF",
|
||||
@ -197,6 +209,12 @@ def t_NAME(t):
|
||||
return t
|
||||
|
||||
|
||||
def t_DIRECTIVE(t):
|
||||
r"%[a-z]+"
|
||||
t.value = t.value[1:]
|
||||
return t
|
||||
|
||||
|
||||
def t_STRING(t):
|
||||
r"""(?x) # verbose mode
|
||||
(?<!\\) # not preceded by a backslash
|
||||
@ -220,7 +238,7 @@ def t_STRING(t):
|
||||
|
||||
|
||||
def t_FLOATINGPOINT(t):
|
||||
r"[-+]? (?: (?: \d* \. \d+ ) | (?: \d+ \.? ) )(?: [Ee] [+-]? \d+ ) ?"
|
||||
r"((?: (?: \d* \. \d+ ) | (?: \d+ \.? ) )(?: [Ee] [+-]? \d+ ) ?)(?![a-z])"
|
||||
try:
|
||||
t.value = int(t.value)
|
||||
t.type = "INTEGER"
|
||||
@ -230,7 +248,7 @@ def t_FLOATINGPOINT(t):
|
||||
|
||||
|
||||
def t_INTEGER(t):
|
||||
r"([-+]?\$?[a-fA-F\d]+ | [-+]?[\$%]?\d+ | [-+]?%?[01]+)(?!\.)"
|
||||
r"\$?[a-fA-F\d]+ | [\$%]?\d+ | %?[01]+"
|
||||
sign = 1
|
||||
if t.value[0] in "+-":
|
||||
sign = -1 if t.value[0] == "-" else 1
|
||||
@ -245,21 +263,20 @@ def t_INTEGER(t):
|
||||
|
||||
|
||||
def t_COMMENT(t):
|
||||
r";[^\n]*"
|
||||
# don't include the \n at the end, that must be processed by t_newline
|
||||
return None # ignore comments for now
|
||||
r"[ \t]*;[^\n]*" # dont eat newline
|
||||
return None # don't process comments
|
||||
|
||||
|
||||
def t_PRESERVEREGS(t):
|
||||
r"!\s*[AXY]{0,3}\s*"
|
||||
r"!\s*[AXY]{0,3}\s*(?!=)"
|
||||
t.value = t.value[1:-1].strip()
|
||||
return t
|
||||
|
||||
|
||||
def t_newline(t):
|
||||
def t_ENDL(t):
|
||||
r"\n+"
|
||||
t.lexer.lineno += len(t.value)
|
||||
return None # ignore white space tokens
|
||||
return t # end of lines are significant to the parser
|
||||
|
||||
|
||||
def t_error(t):
|
||||
|
295
il65/plyacc.py
295
il65/plyacc.py
@ -66,6 +66,12 @@ class SubCall(AstNode):
|
||||
self.arguments = arguments
|
||||
|
||||
|
||||
class Return(AstNode):
|
||||
def __init__(self, value, sourceref):
|
||||
super().__init__(sourceref)
|
||||
self.value = value
|
||||
|
||||
|
||||
class InlineAssembly(AstNode):
|
||||
def __init__(self, assembly, sourceref):
|
||||
super().__init__(sourceref)
|
||||
@ -105,6 +111,27 @@ class Goto(AstNode):
|
||||
self.condition = condition
|
||||
|
||||
|
||||
class Dereference(AstNode):
|
||||
def __init__(self, location, datatype, sourceref):
|
||||
super().__init__(sourceref)
|
||||
self.location = location
|
||||
self.datatype = datatype
|
||||
|
||||
|
||||
class CallTarget(AstNode):
|
||||
def __init__(self, target, address_of: bool, sourceref: SourceRef) -> None:
|
||||
super().__init__(sourceref)
|
||||
self.target = target
|
||||
self.address_of = address_of
|
||||
|
||||
|
||||
class CallArgument(AstNode):
|
||||
def __init__(self, name, value, sourceref):
|
||||
super().__init__(sourceref)
|
||||
self.name = name
|
||||
self.value = value
|
||||
|
||||
|
||||
class UnaryOp(AstNode):
|
||||
def __init__(self, operator, operand, sourceref):
|
||||
super().__init__(sourceref)
|
||||
@ -143,14 +170,15 @@ def p_module(p):
|
||||
|
||||
|
||||
def p_module_elt(p):
|
||||
"""module_elt : directive
|
||||
| block"""
|
||||
"""module_elt : ENDL
|
||||
| directive
|
||||
| block """
|
||||
p[0] = p[1]
|
||||
|
||||
|
||||
def p_directive(p):
|
||||
"""directive : DIRECTIVE
|
||||
| DIRECTIVE directive_args
|
||||
"""directive : DIRECTIVE ENDL
|
||||
| DIRECTIVE directive_args ENDL
|
||||
"""
|
||||
if len(p) == 2:
|
||||
p[0] = Directive(p[1], None, _token_sref(p, 1))
|
||||
@ -176,11 +204,25 @@ def p_directive_arg(p):
|
||||
p[0] = p[1]
|
||||
|
||||
|
||||
def p_block_name_addr(p):
|
||||
"""block : BITINVERT NAME INTEGER endl_opt scope"""
|
||||
p[0] = Block(p[2], p[3], p[5], _token_sref(p, 1))
|
||||
|
||||
|
||||
def p_block_name(p):
|
||||
"""block : BITINVERT NAME endl_opt scope"""
|
||||
p[0] = Block(p[2], None, p[4], _token_sref(p, 1))
|
||||
|
||||
|
||||
def p_block(p):
|
||||
"""block : TILDE NAME INTEGER scope
|
||||
| TILDE NAME empty scope
|
||||
| TILDE empty empty scope"""
|
||||
p[0] = Block(p[2], p[3], p[4], _token_sref(p, 1))
|
||||
"""block : BITINVERT endl_opt scope"""
|
||||
p[0] = Block(None, None, p[3], _token_sref(p, 1))
|
||||
|
||||
|
||||
def p_endl_opt(p):
|
||||
"""endl_opt : empty
|
||||
| ENDL"""
|
||||
p[0] = p[1]
|
||||
|
||||
|
||||
def p_scope(p):
|
||||
@ -204,10 +246,11 @@ def p_scope_elements(p):
|
||||
|
||||
|
||||
def p_scope_element(p):
|
||||
"""scope_element : directive
|
||||
"""scope_element : ENDL
|
||||
| label
|
||||
| directive
|
||||
| vardef
|
||||
| subroutine
|
||||
| label
|
||||
| inlineasm
|
||||
| statement"""
|
||||
p[0] = p[1]
|
||||
@ -219,26 +262,27 @@ def p_label(p):
|
||||
|
||||
|
||||
def p_inlineasm(p):
|
||||
"""inlineasm : INLINEASM"""
|
||||
"""inlineasm : INLINEASM ENDL"""
|
||||
p[0] = InlineAssembly(p[1], _token_sref(p, 1))
|
||||
|
||||
|
||||
def p_vardef(p):
|
||||
"""vardef : VARTYPE type_opt NAME IS literal_value
|
||||
| VARTYPE type_opt NAME"""
|
||||
if len(p) == 4:
|
||||
p[0] = VarDef(p[3], p[1], p[2], None, _token_sref(p, 1))
|
||||
else:
|
||||
p[0] = VarDef(p[3], p[1], p[2], p[5], _token_sref(p, 1))
|
||||
"""vardef : VARTYPE type_opt NAME ENDL"""
|
||||
p[0] = VarDef(p[3], p[1], p[2], None, _token_sref(p, 1))
|
||||
|
||||
|
||||
def p_vardef_value(p):
|
||||
"""vardef : VARTYPE type_opt NAME IS expression"""
|
||||
p[0] = VarDef(p[3], p[1], p[2], p[5], _token_sref(p, 1))
|
||||
|
||||
|
||||
def p_type_opt(p):
|
||||
"""type_opt : DATATYPE
|
||||
| DATATYPE '(' dimensions ')'
|
||||
"""type_opt : DATATYPE '(' dimensions ')'
|
||||
| DATATYPE
|
||||
| empty"""
|
||||
if len(p) == 4:
|
||||
p[0] = Datatype(p[1], p[3], _token_sref(p, 1))
|
||||
elif p:
|
||||
elif len(p) == 2:
|
||||
p[0] = Datatype(p[1], None, _token_sref(p, 1))
|
||||
|
||||
|
||||
@ -261,7 +305,7 @@ def p_literal_value(p):
|
||||
|
||||
|
||||
def p_subroutine(p):
|
||||
"""subroutine : SUB NAME '(' sub_param_spec ')' RARROW '(' sub_result_spec ')' subroutine_body"""
|
||||
"""subroutine : SUB NAME '(' sub_param_spec ')' RARROW '(' sub_result_spec ')' subroutine_body ENDL"""
|
||||
p[0] = Subroutine(p[2], p[4], p[8], p[10], _token_sref(p, 1))
|
||||
|
||||
|
||||
@ -282,13 +326,11 @@ def p_sub_param_list(p):
|
||||
|
||||
def p_sub_param(p):
|
||||
"""sub_param : LABEL REGISTER
|
||||
| empty REGISTER"""
|
||||
p[0] = (p[1], p[2])
|
||||
|
||||
|
||||
def p_param_name(p):
|
||||
"""param_name : NAME ':'"""
|
||||
p[0] = p[1]
|
||||
| REGISTER"""
|
||||
if len(p) == 3:
|
||||
p[0] = (p[1], p[2])
|
||||
elif len(p) == 2:
|
||||
p[0] = (None, p[1])
|
||||
|
||||
|
||||
def p_sub_result_spec(p):
|
||||
@ -325,26 +367,24 @@ def p_subroutine_body(p):
|
||||
|
||||
|
||||
def p_statement(p):
|
||||
"""statement : assignment
|
||||
| subroutine_call
|
||||
| goto
|
||||
| conditional_goto
|
||||
| incrdecr
|
||||
| RETURN
|
||||
"""statement : assignment ENDL
|
||||
| subroutine_call ENDL
|
||||
| goto ENDL
|
||||
| conditional_goto ENDL
|
||||
| incrdecr ENDL
|
||||
| return ENDL
|
||||
"""
|
||||
p[0] = p[1]
|
||||
|
||||
|
||||
def p_incrdecr(p):
|
||||
"""incrdecr : register INCR
|
||||
| register DECR
|
||||
| symbolname INCR
|
||||
| symbolname DECR"""
|
||||
"""incrdecr : assignment_target INCR
|
||||
| assignment_target DECR"""
|
||||
p[0] = UnaryOp(p[2], p[1], _token_sref(p, 1))
|
||||
|
||||
|
||||
def p_call_subroutine(p):
|
||||
"""subroutine_call : symbolname preserveregs_opt '(' call_arguments_opt ')'"""
|
||||
"""subroutine_call : calltarget preserveregs_opt '(' call_arguments_opt ')'"""
|
||||
p[0] = SubCall(p[1], p[3], _token_sref(p, 1))
|
||||
|
||||
|
||||
@ -375,9 +415,22 @@ def p_call_arguments(p):
|
||||
|
||||
|
||||
def p_call_argument(p):
|
||||
"""call_argument : literal_value
|
||||
| register"""
|
||||
p[0] = p[1]
|
||||
"""call_argument : expression
|
||||
| register IS expression
|
||||
| NAME IS expression"""
|
||||
if len(p) == 2:
|
||||
p[0] = CallArgument(None, p[1], _token_sref(p, 1))
|
||||
elif len(p) == 3:
|
||||
p[0] = CallArgument(p[1], p[3], _token_sref(p, 1))
|
||||
|
||||
|
||||
def p_return(p):
|
||||
"""return : RETURN
|
||||
| RETURN expression"""
|
||||
if len(p) == 2:
|
||||
p[0] = Return(None, _token_sref(p, 1))
|
||||
elif len(p) == 4:
|
||||
p[0] = Return(p[3], _token_sref(p, 1))
|
||||
|
||||
|
||||
def p_register(p):
|
||||
@ -386,17 +439,43 @@ def p_register(p):
|
||||
|
||||
|
||||
def p_goto(p):
|
||||
"""goto : GOTO symbolname
|
||||
| GOTO INTEGER"""
|
||||
"""goto : GOTO calltarget"""
|
||||
p[0] = Goto(p[2], None, None, _token_sref(p, 1))
|
||||
|
||||
|
||||
def p_conditional_goto(p):
|
||||
"""conditional_goto : IF GOTO symbolname"""
|
||||
# @todo support conditional expression
|
||||
def p_conditional_goto_plain(p):
|
||||
"""conditional_goto : IF GOTO calltarget"""
|
||||
p[0] = Goto(p[3], p[1], None, _token_sref(p, 1))
|
||||
|
||||
|
||||
def p_conditional_goto_expr(p):
|
||||
"""conditional_goto : IF expression GOTO calltarget"""
|
||||
p[0] = Goto(p[4], p[1], p[2], _token_sref(p, 1))
|
||||
|
||||
|
||||
def p_calltarget(p):
|
||||
"""calltarget : symbolname
|
||||
| INTEGER
|
||||
| BITAND symbolname
|
||||
| dereference"""
|
||||
if len(p) == 2:
|
||||
p[0] = CallTarget(p[1], False, _token_sref(p, 1))
|
||||
elif len(p) == 3:
|
||||
p[0] = CallTarget(p[2], True, _token_sref(p, 1))
|
||||
|
||||
|
||||
def p_dereference(p):
|
||||
"""dereference : '[' dereference_operand ']' """
|
||||
p[0] = Dereference(p[2][0], p[2][1], _token_sref(p, 1))
|
||||
|
||||
|
||||
def p_dereference_operand(p):
|
||||
"""dereference_operand : symbolname type_opt
|
||||
| REGISTER type_opt
|
||||
| INTEGER type_opt"""
|
||||
p[0] = (p[1], p[2])
|
||||
|
||||
|
||||
def p_symbolname(p):
|
||||
"""symbolname : NAME
|
||||
| DOTTEDNAME"""
|
||||
@ -404,8 +483,7 @@ def p_symbolname(p):
|
||||
|
||||
|
||||
def p_assignment(p):
|
||||
"""assignment : assignment_lhs assignment_operator assignment_rhs"""
|
||||
# @todo replace lhs/rhs by expressions
|
||||
"""assignment : assignment_lhs assignment_operator expression"""
|
||||
p[0] = Assignment(p[1], p[2], p[3], _token_sref(p, 1))
|
||||
|
||||
|
||||
@ -415,35 +493,76 @@ def p_assignment_operator(p):
|
||||
p[0] = p[1]
|
||||
|
||||
|
||||
def p_unary_operator(p):
|
||||
"""unary_operator : '+'
|
||||
| '-'
|
||||
| NOT
|
||||
| ADDRESSOF"""
|
||||
precedence = (
|
||||
('left', '+', '-'),
|
||||
('left', '*', '/'),
|
||||
('right', 'UNARY_MINUS', 'BITINVERT', "UNARY_ADDRESSOF"),
|
||||
('left', "LT", "GT", "LE", "GE", "EQUALS", "NOTEQUALS"),
|
||||
('nonassoc', "COMMENT"),
|
||||
)
|
||||
|
||||
|
||||
def p_expression(p):
|
||||
"""expression : expression '+' expression
|
||||
| expression '-' expression
|
||||
| expression '*' expression
|
||||
| expression '/' expression
|
||||
| expression LT expression
|
||||
| expression GT expression
|
||||
| expression LE expression
|
||||
| expression GE expression
|
||||
| expression EQUALS expression
|
||||
| expression NOTEQUALS expression"""
|
||||
pass
|
||||
|
||||
|
||||
def p_expression_uminus(p):
|
||||
"""expression : '-' expression %prec UNARY_MINUS"""
|
||||
pass
|
||||
|
||||
|
||||
def p_expression_addressof(p):
|
||||
"""expression : BITAND symbolname %prec UNARY_ADDRESSOF"""
|
||||
pass
|
||||
|
||||
|
||||
def p_unary_expression_bitinvert(p):
|
||||
"""expression : BITINVERT expression"""
|
||||
pass
|
||||
|
||||
|
||||
def p_expression_group(p):
|
||||
"""expression : '(' expression ')'"""
|
||||
p[0] = p[2]
|
||||
|
||||
|
||||
def p_expression_ass_rhs(p):
|
||||
"""expression : expression_value"""
|
||||
p[0] = p[1]
|
||||
|
||||
|
||||
def p_expression_value(p):
|
||||
"""expression_value : literal_value
|
||||
| symbolname
|
||||
| register
|
||||
| subroutine_call
|
||||
| dereference"""
|
||||
p[0] = p[1]
|
||||
|
||||
|
||||
def p_assignment_lhs(p):
|
||||
"""assignment_lhs : register
|
||||
| symbolname
|
||||
| assignment_lhs ',' register
|
||||
| assignment_lhs ',' symbolname"""
|
||||
"""assignment_lhs : assignment_target
|
||||
| assignment_lhs ',' assignment_target"""
|
||||
if len(p) == 2:
|
||||
p[0] = [p[1]]
|
||||
else:
|
||||
p[0] = p[1] + [p[2]]
|
||||
|
||||
|
||||
def p_assignment_rhs(p):
|
||||
"""assignment_rhs : literal_value
|
||||
| symbolname
|
||||
| register
|
||||
| subroutine_call"""
|
||||
p[0] = p[1]
|
||||
|
||||
|
||||
def p_term(p):
|
||||
"""term : register"""
|
||||
def p_assignment_target(p):
|
||||
"""assignment_target : register
|
||||
| symbolname
|
||||
| dereference"""
|
||||
p[0] = p[1]
|
||||
|
||||
|
||||
@ -454,8 +573,8 @@ def p_empty(p):
|
||||
|
||||
def p_error(p):
|
||||
if p:
|
||||
sref = SourceRef("@todo-filename2", p.lineno, find_tok_column(p))
|
||||
lexer.error_function("{}: before '{:.20s}' ({})", sref, str(p.value), repr(p))
|
||||
sref = SourceRef(p.lexer.source_filename, p.lineno, find_tok_column(p))
|
||||
p.lexer.error_function("{}: before '{:.20s}' ({})", sref, str(p.value), repr(p))
|
||||
else:
|
||||
lexer.error_function("{}: at end of input", "@todo-filename3")
|
||||
|
||||
@ -469,19 +588,39 @@ def _token_sref(p, token_idx):
|
||||
if last_cr < 0:
|
||||
last_cr = -1
|
||||
column = (p.lexpos(token_idx) - last_cr)
|
||||
return SourceRef("@todo-filename", p.lineno(token_idx), column)
|
||||
return SourceRef(p.lexer.source_filename, p.lineno(token_idx), column)
|
||||
|
||||
|
||||
precedence = (
|
||||
('nonassoc', "COMMENT"),
|
||||
)
|
||||
class TokenFilter:
|
||||
def __init__(self, lexer):
|
||||
self.lexer = lexer
|
||||
self.prev_was_EOL = False
|
||||
assert "ENDL" in tokens
|
||||
|
||||
parser = yacc()
|
||||
def token(self):
|
||||
# make sure we only ever emit ONE "ENDL" token in sequence
|
||||
if self.prev_was_EOL:
|
||||
# skip all EOLS that might follow
|
||||
while True:
|
||||
tok = self.lexer.token()
|
||||
if not tok or tok.type != "ENDL":
|
||||
break
|
||||
self.prev_was_EOL = False
|
||||
else:
|
||||
tok = self.lexer.token()
|
||||
self.prev_was_EOL = tok and tok.type == "ENDL"
|
||||
return tok
|
||||
|
||||
|
||||
parser = yacc(write_tables=True)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
file = sys.stdin # open(sys.argv[1], "rU")
|
||||
result = parser.parse(input=file.read()) or Module(None, SourceRef("@todo-sfile", 1, 1))
|
||||
print("RESULT")
|
||||
print(str(result))
|
||||
lexer.source_filename = "derp"
|
||||
tokenfilter = TokenFilter(lexer)
|
||||
result = parser.parse(input=file.read(),
|
||||
tokenfunc=tokenfilter.token) or Module(None, SourceRef(lexer.source_filename, 1, 1))
|
||||
# print("RESULT:")
|
||||
# print(str(result))
|
||||
|
@ -695,8 +695,9 @@ ascii_to_petscii_trans = str.maketrans({
|
||||
|
||||
|
||||
class AstNode:
|
||||
def __init__(self, sourceref: SourceRef) -> None:
|
||||
def __init__(self, sourceref: SourceRef, children: List['AstNode']=None) -> None:
|
||||
self.sourceref = sourceref.copy()
|
||||
self.children = children or []
|
||||
|
||||
@property
|
||||
def lineref(self) -> str:
|
||||
|
@ -1,10 +1,12 @@
|
||||
; call tests
|
||||
|
||||
;output
|
||||
%output foobar
|
||||
|
||||
|
||||
~ foo {
|
||||
|
||||
|
||||
|
||||
var .word var1 = 99
|
||||
memory .word mem1 = $cff0
|
||||
|
||||
@ -20,44 +22,54 @@
|
||||
sub sub3 (XY) -> (Y?) = $ddaa
|
||||
sub sub4 (string: XY, other : A) -> (Y?) = $dd22
|
||||
|
||||
bar2:
|
||||
|
||||
bar:
|
||||
|
||||
goto $c000
|
||||
bar: goto $c000
|
||||
goto var1 ; jumps to the address in var1
|
||||
goto mem1 ; jumps to the address in mem1
|
||||
goto &var1 ; strange, but jumps to the location in memory where var1 sits
|
||||
goto &mem1 ; strange, but jumps to the location in mempory where mem1 sits (points to)
|
||||
goto [var1]
|
||||
goto [$c000.word]
|
||||
goto [var1]
|
||||
goto [mem1]
|
||||
goto var1 ; jumps to the address in var1
|
||||
goto mem1 ; jumps to the address in mem1
|
||||
goto #var1 ; strange, but jumps to the location in memory where var1 sits
|
||||
goto #mem1 ; strange, but jumps to the location in mempory where mem1 sits (points to)
|
||||
|
||||
; ----
|
||||
|
||||
goto sub1
|
||||
goto sub2 (1 )
|
||||
goto sub3 (3)
|
||||
goto sub3 (XY="hello")
|
||||
goto sub3 ("hello, there")
|
||||
goto sub4 (string="hello, there", other = 42)
|
||||
goto sub4 ("hello", 42)
|
||||
goto sub4 ("hello", other= 42)
|
||||
goto sub4 (string="hello", other = 42)
|
||||
goto bar ()
|
||||
;goto sub2 (1 ) ; @todo error, must be return sub2(1) -> optimized in 'tail call'
|
||||
return sub2 ( )
|
||||
return sub2 ()
|
||||
return sub2 (1 )
|
||||
return sub3 (3)
|
||||
return sub3 (XY="hello")
|
||||
return sub3 ("hello, there")
|
||||
return sub4 (string="hello, there", other = 42)
|
||||
return sub4 ("hello", 42)
|
||||
return sub4 ("hello", other= 42)
|
||||
return sub4 (string="hello", other = 42)
|
||||
return bar ()
|
||||
goto [AX]
|
||||
goto [AX] ()
|
||||
; goto [AX()] % ; @todo error, must be return()
|
||||
goto [var1]
|
||||
goto [var1] () ; comment
|
||||
goto [mem1] ; comment
|
||||
goto [mem1] ()
|
||||
goto [$c2.word]
|
||||
goto [$c2.word] ()
|
||||
goto [$c2dd.word]
|
||||
goto [$c2dd.word] ( )
|
||||
goto [mem1] ; comment
|
||||
return [AX]()
|
||||
return [var1] () ; comment
|
||||
return [mem1] ()
|
||||
goto $c000
|
||||
goto $c000 ( )
|
||||
return $c000 ( )
|
||||
goto $c2
|
||||
goto $c2()
|
||||
return $c2()
|
||||
goto [$c2.word]
|
||||
return 33
|
||||
return [$c2.word] ; @todo this as rvalue
|
||||
; [ $c2.word (4) ] ;@ todo parse precedence
|
||||
return [$c2.word] (4)
|
||||
return [$c2.word] (4)
|
||||
return [$c2.word] (4)
|
||||
return [$c2.word] (4)
|
||||
; return [$c2dd.word] ( ) ;@ todo parse precedence
|
||||
goto [$c2dd.word]
|
||||
|
||||
%asm {
|
||||
nop
|
||||
@ -85,8 +97,10 @@ bar:
|
||||
sub3 !AXY (81)
|
||||
|
||||
bar!()
|
||||
bar !()
|
||||
[XY]! ()
|
||||
[XY] ! ()
|
||||
[var1] !()
|
||||
[var1]!()
|
||||
[mem1]!()
|
||||
[$c2.word]!()
|
||||
[$c2dd.word]!()
|
||||
@ -113,8 +127,9 @@ bar:
|
||||
[AX]()
|
||||
[var1] ( )
|
||||
[mem1] ()
|
||||
[$c2.word]()
|
||||
[$c2dd.word]()
|
||||
A= [$c2.word(4)]
|
||||
;A= [$c2.word() ] ; @todo Precedence?
|
||||
;A= [$c2dd.word() ] ; @todo Precedence?
|
||||
$c000()
|
||||
$c2()
|
||||
|
||||
@ -145,4 +160,5 @@ sub unused_sub ()->() {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -3,7 +3,8 @@
|
||||
%import c64lib
|
||||
|
||||
|
||||
~ main {
|
||||
~ main {
|
||||
|
||||
var .word value
|
||||
memory .word memvalue = $8000
|
||||
|
||||
@ -23,7 +24,7 @@ start:
|
||||
if_gt goto label
|
||||
if_cc goto value
|
||||
;if_cc goto memvalue
|
||||
if_cc goto #value
|
||||
if_cc goto &value
|
||||
;if_cc goto #memvalue
|
||||
if_cc goto [value]
|
||||
;if_cc goto [memvalue]
|
||||
@ -66,12 +67,12 @@ label3:
|
||||
if_not [$c000] goto label4
|
||||
if_zero [$c000] goto label4
|
||||
if [$c000] goto label4
|
||||
if_true [XY] goto label4
|
||||
if_true [AY] goto label4
|
||||
if_true [AX] goto label4
|
||||
if_true [X] goto label4
|
||||
if_true [A] goto label4
|
||||
if_true [Y] goto label4
|
||||
if_true [XY] goto label4
|
||||
if_true [AY] goto label4
|
||||
if_true [AX] goto label4
|
||||
if_true [X ] goto label4
|
||||
if_true [A ] goto label4
|
||||
if_true [Y ] goto label4
|
||||
|
||||
label4:
|
||||
return
|
||||
@ -81,9 +82,9 @@ label4:
|
||||
|
||||
; @todo temporarily disabled until comparison operators are properly implemented:
|
||||
|
||||
~ {
|
||||
~ {
|
||||
var bytevar = 22 + 23
|
||||
var .text name = "?"*80
|
||||
var bytevar = 22
|
||||
var bytevar2 = 23
|
||||
var .word wordvar = 22345
|
||||
|
||||
@ -142,3 +143,5 @@ label1:
|
||||
label2:
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
|
@ -64,13 +64,15 @@
|
||||
var .float initfloat4 = 1.70141183e+38
|
||||
var .float initfloat5 = -1.70141183e+38
|
||||
var .float initfloat6 = 1.234
|
||||
var .float (44) zzzz = 333
|
||||
|
||||
var .wordarray ( 10 ) uninit_wordarray
|
||||
var .wordarray(10) init_wordarray = $1234
|
||||
var .wordarray(10) init_wordarrayb = true
|
||||
var .array( 10) uninit_bytearray
|
||||
var .array(10 ) init_bytearray =$12
|
||||
var .array(10 ) init_bytearrayb =true
|
||||
var .array(10 ) init_bytearrayc ='@'
|
||||
var .wordarray( 10 ) uninit_wordarray
|
||||
var .wordarray(10) init_wordarray = $1234
|
||||
var .wordarray(10) init_wordarrayb = true
|
||||
|
||||
var .text text = "hello-null"
|
||||
var .ptext ptext = 'hello-pascal'
|
||||
@ -111,25 +113,27 @@
|
||||
const .pstext ctext6 = "constant-pstext"
|
||||
|
||||
; taking the address of various things:
|
||||
var .word vmemaddr1 = #membyte1
|
||||
var .word vmemaddr2 = #memword1
|
||||
var .word vmemaddr3 = #memfloat
|
||||
var .word vmemaddr4 = #membytes
|
||||
var .word vmemaddr5 = #memwords
|
||||
var .word vmemaddr6 = #memmatrix
|
||||
var .word vmemaddr1 = & membyte1
|
||||
var .word vmemaddr2 = & memword1
|
||||
var .word vmemaddr3 = & memfloat
|
||||
var .word vmemaddr4 = & membytes
|
||||
var .word vmemaddr5 = & memwords
|
||||
var .word vmemaddr6 = & memmatrix
|
||||
var .word vmemaddr8 = 100*sin(cbyte1)
|
||||
var .word vmemaddr9 = cword2+$5432
|
||||
var .word vmemaddr10 = cfloat2b
|
||||
|
||||
; taking the address of things from the ZP will work even when it is a var
|
||||
; because zp-vars get assigned a specific address (from a pool). Also, it's a byte.
|
||||
var .word initword0a = #ZP.zpmem1
|
||||
var .word initword0 = #ZP.zpvar1
|
||||
var initbytea0 = #ZP.zpmem1
|
||||
var .word initworda1 = #ZP.zpvar1
|
||||
|
||||
var .word initword0a = & ZP.zpmem1
|
||||
var .word initword0 = & ZP.zpvar1
|
||||
var initbytea0 = & ZP.zpmem1
|
||||
var .word initworda1 = & ZP.zpvar1
|
||||
|
||||
|
||||
; (constant) expressions
|
||||
var expr_byte1b = -1-2-3-4-$22+0x80+ZP.zpconst
|
||||
var expr_byte1b = -1-2-3-4-$22+$80+ZP.zpconst
|
||||
var .byte expr_fault2 = 1 + (8/3)+sin(33) + max(1,2,3)
|
||||
|
||||
|
||||
@ -177,17 +181,18 @@ start:
|
||||
XY = uninitbyte1
|
||||
XY = "text-immediate"
|
||||
AY = "text-immediate"
|
||||
AX = #"text-immediate" ; equivalent to simply assigning the string directly
|
||||
AX = # "text-immediate" ; equivalent to simply assigning the string directly
|
||||
AX = &derp
|
||||
; AX = &"text-immediate" ; equivalent to simply assigning the string directly
|
||||
; AX = & "text-immediate" ; equivalent to simply assigning the string directly
|
||||
AX = ctext3
|
||||
AX = ""
|
||||
AX = XY
|
||||
AX = Y
|
||||
XY = membyte2
|
||||
XY = #membyte2
|
||||
XY = membyte2
|
||||
XY = memword1
|
||||
XY = sin
|
||||
XY = #sin
|
||||
XY = &sin
|
||||
|
||||
|
||||
[$c000] = A
|
||||
@ -211,7 +216,7 @@ start:
|
||||
[$c000.word] = ""
|
||||
[$c000.word] = uninitbyte1
|
||||
[$c000.word] = membyte2
|
||||
[$c000.word] = #membyte2
|
||||
[$c000.word] = &membyte2
|
||||
[$c000.word] = [cword2]
|
||||
[$c000.word] = memword1
|
||||
[$c000.float] = 65535
|
||||
@ -225,7 +230,7 @@ start:
|
||||
[$c112.word] = [$c223.byte]
|
||||
[$c222.word] = [$c333.word]
|
||||
[$c333.word] = sin
|
||||
[$c333.word] = #sin
|
||||
[$c333.word] = &sin
|
||||
|
||||
|
||||
SC = 0
|
||||
@ -261,7 +266,7 @@ start:
|
||||
uninitfloat = 9.8765
|
||||
uninitfloat = '@'
|
||||
initword1 = sin
|
||||
initword1 = #sin
|
||||
initword1 = &sin
|
||||
|
||||
membyte1 = A
|
||||
membyte1 = cbyte3
|
||||
@ -276,7 +281,7 @@ start:
|
||||
memword1 = 2233
|
||||
memfloat = 3.4567
|
||||
memword1 = sin
|
||||
memword1 = #sin
|
||||
memword1 = &sin
|
||||
|
||||
membyte1 = A
|
||||
memword1 = A
|
||||
@ -304,7 +309,7 @@ start:
|
||||
AY = "text-immediate" ; reuses existing
|
||||
AX = "another"
|
||||
AX = ""
|
||||
[$c000.word] = "another" ; reuse
|
||||
[$c100.word] = "text-immediate" ; reuse
|
||||
[$c200.word] = "" ; reuse
|
||||
;*$c000.word = "another" ; reuse @ todo precedence?
|
||||
;*$c100.word = "text-immediate" ; reuse @ todo precedence?
|
||||
;*$c200.word = "" ; reuse @ todo precedence?
|
||||
}
|
||||
|
@ -54,10 +54,10 @@ sub printflt (float: AY) -> (?) {
|
||||
|
||||
start:
|
||||
; assign some float values to the memory
|
||||
AY = #flt_pi
|
||||
some_address = # flt_pi
|
||||
AY = &flt_pi
|
||||
some_address = & flt_pi
|
||||
some_address = 4123.2342342222
|
||||
[$c000.word] = # flt_pi
|
||||
[$c000.word] = & flt_pi
|
||||
|
||||
my_float ++
|
||||
my_float += 1
|
||||
@ -70,47 +70,47 @@ start:
|
||||
|
||||
; print some floating points from source and compare them with ROM
|
||||
|
||||
printflt(#flt_pi)
|
||||
printflt(#c64.FL_PIVAL)
|
||||
printflt(&flt_pi)
|
||||
printflt(&c64.FL_PIVAL)
|
||||
|
||||
printflt(#flt_minus32768)
|
||||
printflt(#c64.FL_N32768)
|
||||
printflt(&flt_minus32768)
|
||||
printflt(&c64.FL_N32768)
|
||||
|
||||
printflt(#flt_1)
|
||||
printflt(#c64.FL_FONE)
|
||||
printflt(&flt_1)
|
||||
printflt(&c64.FL_FONE)
|
||||
|
||||
printflt(#flt_half_sqr2)
|
||||
printflt( # c64.FL_SQRHLF)
|
||||
printflt(&flt_half_sqr2)
|
||||
printflt( & c64.FL_SQRHLF)
|
||||
|
||||
printflt(#flt_sqr2)
|
||||
printflt(#c64.FL_SQRTWO)
|
||||
printflt(&flt_sqr2)
|
||||
printflt(&c64.FL_SQRTWO)
|
||||
|
||||
printflt(#flt_minus_half)
|
||||
printflt(#c64.FL_NEGHLF)
|
||||
printflt(&flt_minus_half)
|
||||
printflt(&c64.FL_NEGHLF)
|
||||
|
||||
printflt(#flt_log_2)
|
||||
printflt(#c64.FL_LOG2)
|
||||
printflt(&flt_log_2)
|
||||
printflt(&c64.FL_LOG2)
|
||||
|
||||
printflt(#flt_10)
|
||||
printflt(#c64.FL_TENC)
|
||||
printflt(&flt_10)
|
||||
printflt(&c64.FL_TENC)
|
||||
|
||||
printflt(#flt_1e9)
|
||||
printflt(#c64.FL_NZMIL)
|
||||
printflt(&flt_1e9)
|
||||
printflt(&c64.FL_NZMIL)
|
||||
|
||||
printflt(#flt_half)
|
||||
printflt(#c64.FL_FHALF)
|
||||
printflt(&flt_half)
|
||||
printflt(&c64.FL_FHALF)
|
||||
|
||||
printflt(#flt_one_over_log_2)
|
||||
printflt(#c64.FL_LOGEB2)
|
||||
printflt(&flt_one_over_log_2)
|
||||
printflt(&c64.FL_LOGEB2)
|
||||
|
||||
printflt(#flt_half_pi)
|
||||
printflt(#c64.FL_PIHALF)
|
||||
printflt(&flt_half_pi)
|
||||
printflt(&c64.FL_PIHALF)
|
||||
|
||||
printflt(#flt_double_pi)
|
||||
printflt(#c64.FL_TWOPI)
|
||||
printflt(&flt_double_pi)
|
||||
printflt(&c64.FL_TWOPI)
|
||||
|
||||
printflt(# flt_point25)
|
||||
printflt(#c64.FL_FR4)
|
||||
printflt(& flt_point25)
|
||||
printflt(&c64.FL_FR4)
|
||||
|
||||
reg_to_float:
|
||||
c64.CHROUT!('\n')
|
||||
@ -120,25 +120,25 @@ reg_to_float:
|
||||
Y=55
|
||||
|
||||
my_float = A
|
||||
printflt(#my_float)
|
||||
printflt(&my_float)
|
||||
|
||||
my_float = X
|
||||
printflt(#my_float)
|
||||
printflt(&my_float)
|
||||
|
||||
my_float = Y
|
||||
printflt(#my_float)
|
||||
printflt(&my_float)
|
||||
|
||||
XY = 11122
|
||||
my_float = XY
|
||||
printflt(#my_float)
|
||||
printflt(&my_float)
|
||||
|
||||
AX = 33344
|
||||
my_float = AX
|
||||
printflt(#my_float)
|
||||
printflt(&my_float)
|
||||
|
||||
AY = 55566
|
||||
my_float = AY
|
||||
printflt(#my_float)
|
||||
printflt(&my_float)
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ start:
|
||||
|
||||
orig_irq = c64.CINV
|
||||
SI = 1
|
||||
c64.CINV = #irq_handler
|
||||
c64.CINV = &irq_handler
|
||||
SI = 0
|
||||
|
||||
|
||||
@ -20,7 +20,11 @@ start:
|
||||
c64.CHROUT('\n')
|
||||
|
||||
blop:
|
||||
%breakpoint ; yeah!
|
||||
return
|
||||
%breakpoint
|
||||
return
|
||||
|
||||
; yeah!
|
||||
|
||||
c64scr.print_string("thank you, mr or mrs: ")
|
||||
c64scr.print_string(name)
|
||||
@ -44,4 +48,4 @@ irq_handler:
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
1200
testsource/large.ill
1200
testsource/large.ill
File diff suppressed because it is too large
Load Diff
@ -8,7 +8,7 @@
|
||||
%zp restore , clobber ; clobber over the zp memory normally used by basic/kernel rom, frees up more zp
|
||||
|
||||
|
||||
~main $0a00
|
||||
~ main $0a00
|
||||
{
|
||||
; this is the main block with the start routine.
|
||||
|
||||
@ -33,7 +33,7 @@ start: ;foo
|
||||
Y = X
|
||||
X = 66
|
||||
screen = 0
|
||||
screen = border = cursor = X = Y = A = X = Y = A = border = cursor = border = cursor = 66 ; multi-assign!
|
||||
screen = border = cursor = X = Y = A = X = Y = A = border = cursor = border = cursor = 66 ; multi-assign! @todo ply parse
|
||||
border = false
|
||||
border = true
|
||||
border = 0
|
||||
@ -98,7 +98,7 @@ sub customsub (Y)->() {
|
||||
|
||||
A=2
|
||||
X=33
|
||||
goto fidget.subroutine()
|
||||
return fidget.subroutine()
|
||||
|
||||
}
|
||||
|
||||
@ -186,8 +186,6 @@ subroutine:
|
||||
;[border2] = red
|
||||
;[screen2] = white
|
||||
return $99
|
||||
return ,$99
|
||||
return ,,$99
|
||||
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ start:
|
||||
c64.CHROUT('1')
|
||||
c64.CHROUT('2')
|
||||
c64scr.print_string(hello)
|
||||
goto c64.CHROUT('!')
|
||||
return c64.CHROUT('!')
|
||||
|
||||
|
||||
return
|
||||
@ -67,9 +67,9 @@ start:
|
||||
~ global2 {
|
||||
|
||||
make_screen_black:
|
||||
c64.EXTCOL = c64.BGCOL0 = 0
|
||||
c64.EXTCOL = c64.BGCOL0 = 0 ; @todo ply parse multiassign
|
||||
c64.COLOR = 3
|
||||
Y = true
|
||||
return
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
%output prg,basic ; create a c-64 program with basic SYS to() launch it
|
||||
|
||||
%import c64lib.ill
|
||||
%import "c64lib.ill"
|
||||
|
||||
~ main
|
||||
{
|
||||
@ -53,8 +53,8 @@ start2:
|
||||
~ global2 {
|
||||
|
||||
make_screen_black:
|
||||
c64.EXTCOL = c64.BGCOL0 = 0
|
||||
c64.EXTCOL = c64.BGCOL0 = 0 ; @todo ply parse multi assign
|
||||
c64.COLOR = 3
|
||||
return
|
||||
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user