From 3c70790fbf0792eaa9229835f1721d9c5a7464ba Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Wed, 3 Jan 2018 21:43:19 +0100 Subject: [PATCH] ply --- il65/lexer.py | 289 +++++++++++++++++++++ il65/plyacc.py | 486 ++++++++++++++++++++++++++++++++++++ lib/c64lib.ill | 2 +- testsource/calls.ill | 4 +- testsource/conditionals.ill | 21 +- testsource/dtypes.ill | 4 +- testsource/floats.ill | 8 +- testsource/input.ill | 10 +- testsource/numbergame.ill | 18 +- testsource/source1.ill | 11 +- testsource/source2.ill | 2 +- testsource/source3.ill | 6 +- testsource/source4.ill | 8 +- todo.ill | 22 +- 14 files changed, 839 insertions(+), 52 deletions(-) create mode 100644 il65/lexer.py create mode 100644 il65/plyacc.py diff --git a/il65/lexer.py b/il65/lexer.py new file mode 100644 index 000000000..d9bf7f377 --- /dev/null +++ b/il65/lexer.py @@ -0,0 +1,289 @@ +import sys +from .symbols import SourceRef +import ply.lex + +# token names + +tokens = ( + "INTEGER", + "FLOATINGPOINT", + "DOTTEDNAME", + "NAME", + "DOT", + "IS", + "CLOBBEREDREGISTER", + "REGISTER", + "COMMENT", + "DIRECTIVE", + "AUGASSIGN", + "EQUAL", + "NOTEQUAL", + "RARROW", + "RETURN", + "TILDE", + "VARTYPE", + "KEYWORD", + "SUB", + "DATATYPE", + "CHARACTER", + "STRING", + "BOOLEAN", + "GOTO", + "INCR", + "DECR", + "NOT", + "LT", + "GT", + "LE", + "GE", + "LABEL", + "IF", + "ADDRESSOF", + "PRESERVEREGS", + "INLINEASM", +) + +literals = ['+', '-', '*', '/', '(', ')', '[', ']', '{', '}', '.', ',', '!', '?', ':'] + +# regex rules for simple tokens + +t_ADDRESSOF = 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_LT = r"<" +t_GT = r">" +t_LE = r"<=" +t_GE = r">=" +t_IF = "if(_[a-z]+)?" +t_RARROW = r"->" + +# ignore inline whitespace +t_ignore = " \t" +t_inlineasm_ignore = " \t\r\n" + + +# states for allowing %asm inclusion of raw assembly +states = ( + ('inlineasm', 'exclusive'), +) + +# reserved words +reserved = { + "sub": "SUB", + "var": "VARTYPE", + "memory": "VARTYPE", + "const": "VARTYPE", + "goto": "GOTO", + "return": "RETURN", + "true": "BOOLEAN", + "false": "BOOLEAN", + "not": "NOT", + "AX": "REGISTER", + "AY": "REGISTER", + "XY": "REGISTER", + "SC": "REGISTER", + "SI": "REGISTER", + "SZ": "REGISTER", + "A": "REGISTER", + "X": "REGISTER", + "Y": "REGISTER", + "if": "IF", + "if_true": "IF", + "if_not": "IF", + "if_ne": "IF", + "if_eq": "IF", + "if_cc": "IF", + "if_cs": "IF", + "if_vc": "IF", + "if_vs": "IF", + "if_gt": "IF", + "if_lt": "IF", + "if_pos": "IF", + "if_get": "IF", +} + + +# rules for tokens with some actions + +def t_inlineasm(t): + r"%asm\s*\{\s*" + t.lexer.code_start = t.lexer.lexpos # Record start position + t.lexer.level = 1 # initial brace level + t.lexer.begin("inlineasm") # enter state 'inlineasm' + t.lexer.lineno += 1 + + +def t_inlineasm_lbrace(t): + r"\{" + t.lexer.level += 1 + + +def t_inlineasm_rbrace(t): + r"\}" + t.lexer.level -= 1 + #if closing brace, return code fragment + if t.lexer.level == 0: + t.value = t.lexer.lexdata[t.lexer.code_start:t.lexer.lexpos-1] + t.type = "INLINEASM" + t.lexer.lineno += t.value.count("\n") + t.lexer.begin("INITIAL") # back to normal lexing rules + return t + + +def t_inlineasm_comment(t): + r";[^\n]*" + pass + + +def t_inlineasm_string(t): + r"""(?x) # verbose mode + (? (?) { } -sub print_word_decimal (word: XY) -> (A?, X? Y?) { +sub print_word_decimal (word: XY) -> (A?, X?, Y?) { ; ---- print the word in X/Y in decimal form, without left padding 0s %asm { jsr word2decimal diff --git a/testsource/calls.ill b/testsource/calls.ill index b3c61d227..696ce34b3 100644 --- a/testsource/calls.ill +++ b/testsource/calls.ill @@ -21,7 +21,7 @@ sub sub4 (string: XY, other : A) -> (Y?) = $dd22 -bar +bar: goto $c000 goto [$c000.word] @@ -134,7 +134,7 @@ bar ~ main { -start +start: foo.bar() return diff --git a/testsource/conditionals.ill b/testsource/conditionals.ill index 45789fab1..fddad5b79 100644 --- a/testsource/conditionals.ill +++ b/testsource/conditionals.ill @@ -1,13 +1,14 @@ %output prg,basic -%import "c64lib" +%import c64lib + ~ main { var .word value memory .word memvalue = $8000 -start +start: A = 100 @@ -29,7 +30,7 @@ start ;if_cc goto $c000 ;if_cc goto [$c000.word] -label +label: ; conditional if with a single 'truth' value (register) if_true A goto label2 if_not A goto label2 @@ -48,7 +49,7 @@ label if_zero XY goto label2 if XY goto label2 -label2 +label2: ; conditional if with a single 'truth' value (variable) if_true value goto label3 if_not value goto label3 @@ -59,7 +60,7 @@ label2 if_zero memvalue goto label3 if memvalue goto label3 -label3 +label3: ; conditional if with a single 'truth' value (indirect address) if_true [$c000] goto label4 if_not [$c000] goto label4 @@ -72,7 +73,7 @@ label3 if_true [A] goto label4 if_true [Y] goto label4 -label4 +label4: return } @@ -87,18 +88,18 @@ label4 var .word wordvar = 22345 -start +start: c64.init_system() A = 0 -printloop +printloop: c64scr.print_byte_decimal(A) c64.CHROUT('\n') A++ if A <20 goto printloop return -label1 +label1: if_true A==123 goto label1 if_true A == 123 goto label1 if_true A!=0 goto label1 @@ -138,6 +139,6 @@ label1 if_true wordvar goto label2 -label2 +label2: return } diff --git a/testsource/dtypes.ill b/testsource/dtypes.ill index 84398466d..9ccd50731 100644 --- a/testsource/dtypes.ill +++ b/testsource/dtypes.ill @@ -4,7 +4,7 @@ %zp clobber -%import "c64lib" +%import c64lib ~ ZP { ; ZeroPage block definition: @@ -72,7 +72,7 @@ var .wordarray(10) init_wordarray = $1234 var .wordarray(10) init_wordarrayb = true - var .text text = "hello"+"-null" + var .text text = "hello-null" var .ptext ptext = 'hello-pascal' var .stext stext = 'screencodes-null' var .pstext pstext = "screencodes-pascal" diff --git a/testsource/floats.ill b/testsource/floats.ill index 92780f8e5..20e3e127f 100644 --- a/testsource/floats.ill +++ b/testsource/floats.ill @@ -2,10 +2,10 @@ %output prg, basic -%import "c64lib" +%import c64lib ~ main_testing { -start +start: var .float myfloat1 = 1234.56789 var .float myfloat2 = 9876.54321 var .float myfloatneg1 = -555.666 @@ -52,7 +52,7 @@ sub printflt (float: AY) -> (?) { } -start +start: ; assign some float values to the memory AY = #flt_pi some_address = # flt_pi @@ -112,7 +112,7 @@ start printflt(# flt_point25) printflt(#c64.FL_FR4) -reg_to_float +reg_to_float: c64.CHROUT!('\n') A=33 diff --git a/testsource/input.ill b/testsource/input.ill index c92ad2e96..3b3a8ac76 100644 --- a/testsource/input.ill +++ b/testsource/input.ill @@ -1,12 +1,12 @@ %output prg,basic -%import "c64lib" +%import c64lib ~ main { - var .text name = "?"*80 + var .text name = "????????????????????????????????????????????????????????????????????????????????" ; 80 var .word orig_irq -start +start: c64.init_system() orig_irq = c64.CINV @@ -19,7 +19,7 @@ start c64scr.input_chars(name) c64.CHROUT('\n') -blop +blop: %breakpoint ; yeah! c64scr.print_string("thank you, mr or mrs: ") @@ -33,7 +33,7 @@ blop return -irq_handler +irq_handler: %asm { lda c64.SFDX cmp #$40 ; nothing pressed? diff --git a/testsource/numbergame.ill b/testsource/numbergame.ill index b208c407b..588051111 100644 --- a/testsource/numbergame.ill +++ b/testsource/numbergame.ill @@ -1,6 +1,6 @@ %output prg,basic -%import "c64lib" -%import "mathlib" +%import c64lib +%import mathlib ~ main { var .text name = '?' * 80 @@ -9,7 +9,7 @@ var attempts_left = 10 -start +start: c64.init_system() A = c64.VMCSB @@ -41,7 +41,7 @@ start c64scr.print_string("I am thinking of a number from 1 to 100!You'll have to guess it!\n") -printloop +printloop: c64scr.print_string("\nYou have ") c64scr.print_byte_decimal(attempts_left) c64scr.print_string(" guess") @@ -51,7 +51,7 @@ printloop A-- if_zero A goto ask_guess c64scr.print_string("es") -ask_guess +ask_guess: c64scr.print_string(" left.\nWhat is your next guess? ") Y = c64scr.input_chars(guess) c64.CHROUT('\n') @@ -65,21 +65,21 @@ ask_guess c64scr.print_string("low!\n") goto continue -correct_guess +correct_guess: c64scr.print_string("\nThat's my number, impressive!\n") goodbye() return -too_high +too_high: c64scr.print_string("That is too ") c64scr.print_string("high!\n") -continue +continue: attempts_left-- if_zero attempts_left goto game_over goto printloop -game_over +game_over: c64scr.print_string("\nToo bad! It was: ") c64scr.print_byte_decimal(secretnumber) c64.CHROUT('\n') diff --git a/testsource/source1.ill b/testsource/source1.ill index 58a65f701..9ebd7f2b6 100644 --- a/testsource/source1.ill +++ b/testsource/source1.ill @@ -26,7 +26,7 @@ var .wordarray(10) words2 = $bbcc -start ;foo +start: ;foo X = 55 Y = $77 Y = X @@ -63,7 +63,7 @@ start ;foo ; [646,Y] = [$d020,X] -_loop block2.zpw1 ++ +_loop: block2.zpw1 ++ A ++ X ++ Y ++ @@ -103,7 +103,7 @@ sub customsub (Y)->() { } -somelabel1222 +somelabel1222: customsub(2) return @@ -119,7 +119,7 @@ somelabel1222 } ~ block3 { -somelabel1 +somelabel1: %asm { nop nop @@ -180,7 +180,8 @@ somelabel1 ~ fidget $1000 { -subroutine +subroutine: + ; subroutine (A, X, Y) ;[border2] = red ;[screen2] = white diff --git a/testsource/source2.ill b/testsource/source2.ill index d543b3fb5..5aab918d3 100644 --- a/testsource/source2.ill +++ b/testsource/source2.ill @@ -7,7 +7,7 @@ } ~ main { -start +start: A=0 [$d020]=A X=false diff --git a/testsource/source3.ill b/testsource/source3.ill index d81093cd0..a040b31e3 100644 --- a/testsource/source3.ill +++ b/testsource/source3.ill @@ -2,7 +2,7 @@ %output prg,basic ; create a c-64 program with basic SYS call to launch it -%import "c64lib" ; searched in several locations and with .ill file extension added +%import c64lib ; searched in several locations and with .ill file extension added ~ main { @@ -24,7 +24,7 @@ var .text hello2 = "@@\f\b\n\r\t@@" -start +start: global2.make_screen_black() A='?' @@ -66,7 +66,7 @@ start ~ global2 { -make_screen_black +make_screen_black: c64.EXTCOL = c64.BGCOL0 = 0 c64.COLOR = 3 Y = true diff --git a/testsource/source4.ill b/testsource/source4.ill index 73a048272..c121bea63 100644 --- a/testsource/source4.ill +++ b/testsource/source4.ill @@ -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 { @@ -8,7 +8,7 @@ var .ptext p_greeting = "hello world!\r12345678 is a big number.\r" const .word BORDER = $d020 -start +start: c64scr.print_pimmediate() ; this prints the pstring immediately following it %asm { .ptext "hello-pimmediate!{cr}" @@ -26,7 +26,7 @@ start c64.CHROUT (13) return -start2 +start2: global2.make_screen_black() c64.CLEARSCR() c64scr.print_string(greeting) @@ -52,7 +52,7 @@ start2 ~ global2 { -make_screen_black +make_screen_black: c64.EXTCOL = c64.BGCOL0 = 0 c64.COLOR = 3 return diff --git a/todo.ill b/todo.ill index 642e11f32..a16aa6f29 100644 --- a/todo.ill +++ b/todo.ill @@ -1,6 +1,6 @@ %output prg,basic -%import "c64lib" -%import "mathlib" +%import c64lib +%import mathlib ~ main { @@ -9,9 +9,9 @@ var var1 =2 var .word wvar1 = 2 -start +start: A=math.randbyte() - A+=c64.RASTER + A += c64.RASTER A-=c64.TIME_LO X,A=math.divmod_bytes(A, 99) c64scr.print_byte_decimal(A) @@ -19,7 +19,7 @@ start return -rndloop +rndloop: XY = math.randword() %asm { txa @@ -76,6 +76,10 @@ rndloop X >>= 7 X >>= 8 X >>= 22 + XY = 1 + AX = 2 + SC =2 + QW =3 ;XY <<= 0 ;XY <<= 1 ;XY <<= 2 @@ -114,7 +118,7 @@ rndloop bne - } -loop +loop : A=c64.GETIN() if_not goto loop c64scr.scroll_right_full(1) @@ -133,6 +137,12 @@ loop Y = $33 c64scr.clear_screen (81, 5) + c64scr.clear_screen (81, 5) + c64scr.clear_screen (81, 5) + c64scr.clear_screen (81, 5) + c64scr.clear_screen ! (81, 5) + c64scr.clear_screen ! (81, 5) + c64scr.clear_screen !(81, 5) c64scr.clear_screen !(81, 5) c64scr.clear_screen !A (81, 5) c64scr.clear_screen !X (81, 5)