diff --git a/assemble_aux.c b/assemble_aux.c index ac3a24f..894342c 100644 --- a/assemble_aux.c +++ b/assemble_aux.c @@ -225,6 +225,7 @@ void implicit_gbl( case EX_DIV: case EX_AND: case EX_OR: + case EX_LSH: implicit_gbl(value->data.child.right); /* FALLS THROUGH */ case EX_COM: diff --git a/extree.c b/extree.c index 3b5808d..eca608d 100644 --- a/extree.c +++ b/extree.c @@ -112,6 +112,14 @@ void print_tree( print_tree(printfile, tp->data.child.right, depth + 4); fputc('>', printfile); break; + + case EX_LSH: + fputc('<', printfile); + print_tree(printfile, tp->data.child.left, depth + 4); + fputc('_', printfile); + print_tree(printfile, tp->data.child.right, depth + 4); + fputc('>', printfile); + break; } if (depth == 0) @@ -150,6 +158,7 @@ void free_tree( case EX_DIV: case EX_AND: case EX_OR: + case EX_LSH: free_tree(tp->data.child.left); free_tree(tp->data.child.right); break; @@ -244,6 +253,7 @@ EX_TREE *dup_tree( case EX_DIV: case EX_AND: case EX_OR: + case EX_LSH: res->data.child.left = dup_tree(tp->data.child.left); res->data.child.right = dup_tree(tp->data.child.right); break; @@ -703,6 +713,28 @@ EX_TREE *evaluate( res = new_ex_bin(EX_OR, left, right); } break; + + case EX_LSH: + { + EX_TREE *left, + *right; + + left = evaluate(tp->data.child.left, undef); + right = evaluate(tp->data.child.right, undef); + + /* Operate if both are literals */ + if (left->type == EX_LIT && right->type == EX_LIT) { + res = new_ex_lit(left->data.lit << right->data.lit); + free_tree(left); + free_tree(right); + break; + } + + /* Anything else returns verbatim */ + res = new_ex_bin(EX_LSH, left, right); + } + break; + default: fprintf(stderr, "Invalid tree\n"); return NULL; diff --git a/extree.h b/extree.h index ee72a00..645af17 100644 --- a/extree.h +++ b/extree.h @@ -31,7 +31,10 @@ typedef struct ex_tree { /* Divide */ EX_AND = 12, /* bitwise and */ - EX_OR = 13 /* bitwise or */ + EX_OR = 13, + /* bitwise or */ + EX_LSH = 14 + /* left shift */ } type; char *cp; /* points to end of parsed expression */ diff --git a/parse.c b/parse.c index 8ceab19..18c0aa5 100644 --- a/parse.c +++ b/parse.c @@ -596,6 +596,7 @@ int parse_float( #define MUL_PREC 1 #define AND_PREC 1 #define OR_PREC 1 +#define LSH_PREC 1 EX_TREE *parse_unary( char *cp); /* Prototype for forward calls */ @@ -678,6 +679,16 @@ EX_TREE *parse_binary( leftp = tp; break; + case '_': + if (symbol_allow_underscores || depth >= LSH_PREC) + return leftp; + + rightp = parse_binary(cp + 1, term, LSH_PREC); + tp = new_ex_bin(EX_LSH, leftp, rightp); + tp->cp = rightp->cp; + leftp = tp; + break; + default: /* Some unknown character. Let caller decide if it's okay. */ diff --git a/tests/test-prec.lst.ok b/tests/test-prec.lst.ok index ebcac3f..612ece5 100644 --- a/tests/test-prec.lst.ok +++ b/tests/test-prec.lst.ok @@ -20,111 +20,117 @@ 20 000022 000003 .word 12. / 4 ; 000003 21 000024 000121 .word 123 & 771 ; 000121 22 000026 123323 .word 123121 ! 322 ; 123323 - 23 - 24 000030 177401 .word - 377 ; 177401 - 25 000032 000377 .word + 377 ; 000377 - 26 - 27 000034 177400 .word ^C 377 ; 177400 - 28 000036 177400 .word ^c 377 ; 177400 - 29 000040 052525 .word ^B 0101010101010101 ; 052525 - 30 000042 125252 .word ^b 1010101010101010 ; 125252 - 31 000044 000144 .word ^d 100 ; 000144 - 32 000046 000144 .word 100. ; 000144 - 33 000050 000400 .word ^x 100 ; 000400 hexadecimal is an extension - 34 000052 070254 .word ^rRAD ; 070254 up to 3 characters; no leading spaces - 35 000054 003100 .word ^rA ; 003100 up to 3 characters - 36 000056 000050 .word ^r A ; 000050 up to 3 characters - 37 000060 000001 .word ^r A ; 000001 up to 3 characters - 38 000062 000051 .word ^r AA ; 000051 - 39 000064 003101 .word ^rA A ; 003101 - 40 000066 003150 .word ^rAA ; 003150 - 41 000070 003151 .word ^r^/AAA/ ; bracketed strings are an extension - 42 000072 070254 .word ^r ; bracketed strings are an extension - 43 000074 000054 .word ^r< AD> ; bracketed strings are an extension - 44 000076 000004 .word ^r< D> ; bracketed strings are an extension - 45 000100 070204 .word ^r ; bracketed strings are an extension - 46 000102 070250 .word ^r ; bracketed strings are an extension - 47 000104 157614 .word ^R50. ; 157614 there is no whitespace in between. - 48 000106 040300 .word ^f 1.5 ; 040300 - 49 - 50 ;;;;; - 51 ; - 52 ; Test bracketing - 53 ; - 54 000110 000007 .word 1 + < 2 * 3 > ; 1 + 6 = 7 - 55 000112 000007 .word 1 + ^! 2 * 3 ! ; 1 + 6 = 7 - 56 000114 000007 .word 1 + ^/ 2 * 3 / ; 1 + 6 = 7 - 57 000116 000007 .word 1 + ^$ 2 * 3 $ ; 1 + 6 = 7 -test-prec.mac:58: ***ERROR Invalid expression - 58 000120 000003 000000 .word 1 + ^* 2 * 3 * ; Invalid expression - 59 - 60 ;;;;; - 61 ; - 62 ; There was an obscure bug in parse_expr(), used to evaluate 'if df', - 63 ; where it could skip past the end of the line marker. - 64 ; - 65 ; If this happened inside an expanded macro, then after that was the - 66 ; next line... - 67 ; In other cases it might be worse. - 68 ; - 69 .macro dirdef name, flags, cond - 70 .rad50 /.'name/ - 71 .byte flags+0, 0 - 72 .if df cond - 73 .globl opcerr - 74 .word opcerr - 75 .iff - 76 .globl name - 77 .word name - 78 .endc - 79 .endm - 80 - 81 000124 dirdef name - 1 000124 130461 051010 .rad50 /.name/ - 2 000130 000 000 .byte +0, 0 + 23 000005 five = 5 + 24 000030 001230 a: .word 123 _ 3 ; 001230 + 25 000032 000500 .word five _ 6 ; 000500 + 26 000034 004040 .word 101_five ; 004040 +test-prec.mac:27: ***ERROR Invalid expression + 27 000036 000000 .word a _ 3 ; Invalid expression + 28 + 29 000040 177401 .word - 377 ; 177401 + 30 000042 000377 .word + 377 ; 000377 + 31 + 32 000044 177400 .word ^C 377 ; 177400 + 33 000046 177400 .word ^c 377 ; 177400 + 34 000050 052525 .word ^B 0101010101010101 ; 052525 + 35 000052 125252 .word ^b 1010101010101010 ; 125252 + 36 000054 000144 .word ^d 100 ; 000144 + 37 000056 000144 .word 100. ; 000144 + 38 000060 000400 .word ^x 100 ; 000400 hexadecimal is an extension + 39 000062 070254 .word ^rRAD ; 070254 up to 3 characters; no leading spaces + 40 000064 003100 .word ^rA ; 003100 up to 3 characters + 41 000066 000050 .word ^r A ; 000050 up to 3 characters + 42 000070 000001 .word ^r A ; 000001 up to 3 characters + 43 000072 000051 .word ^r AA ; 000051 + 44 000074 003101 .word ^rA A ; 003101 + 45 000076 003150 .word ^rAA ; 003150 + 46 000100 003151 .word ^r^/AAA/ ; bracketed strings are an extension + 47 000102 070254 .word ^r ; bracketed strings are an extension + 48 000104 000054 .word ^r< AD> ; bracketed strings are an extension + 49 000106 000004 .word ^r< D> ; bracketed strings are an extension + 50 000110 070204 .word ^r ; bracketed strings are an extension + 51 000112 070250 .word ^r ; bracketed strings are an extension + 52 000114 157614 .word ^R50. ; 157614 there is no whitespace in between. + 53 000116 040300 .word ^f 1.5 ; 040300 + 54 + 55 ;;;;; + 56 ; + 57 ; Test bracketing + 58 ; + 59 000120 000007 .word 1 + < 2 * 3 > ; 1 + 6 = 7 + 60 000122 000007 .word 1 + ^! 2 * 3 ! ; 1 + 6 = 7 + 61 000124 000007 .word 1 + ^/ 2 * 3 / ; 1 + 6 = 7 + 62 000126 000007 .word 1 + ^$ 2 * 3 $ ; 1 + 6 = 7 +test-prec.mac:63: ***ERROR Invalid expression + 63 000130 000003 000000 .word 1 + ^* 2 * 3 * ; Invalid expression + 64 + 65 ;;;;; + 66 ; + 67 ; There was an obscure bug in parse_expr(), used to evaluate 'if df', + 68 ; where it could skip past the end of the line marker. + 69 ; + 70 ; If this happened inside an expanded macro, then after that was the + 71 ; next line... + 72 ; In other cases it might be worse. + 73 ; + 74 .macro dirdef name, flags, cond + 75 .rad50 /.'name/ + 76 .byte flags+0, 0 + 77 .if df cond + 78 .globl opcerr + 79 .word opcerr + 80 .iff + 81 .globl name + 82 .word name + 83 .endc + 84 .endm + 85 + 86 000134 dirdef name + 1 000134 130461 051010 .rad50 /.name/ + 2 000140 000 000 .byte +0, 0 3 .if df 4 .globl opcerr 5 .word opcerr 6 .iff 7 .globl name - 8 000132 000000G .word name + 8 000142 000000G .word name 9 .endc - 82 -test-prec.mac:83: ***ERROR Invalid expression in .WORD - 83 .word ( -test-prec.mac:84: ***ERROR Invalid expression in .WORD - 84 ( - 85 -test-prec.mac:86: ***ERROR Invalid expression in .WORD - 86 .word _,$ -test-prec.mac:87: ***ERROR Invalid expression in .WORD - 87 _ - 88 000134 000000G $ + 87 +test-prec.mac:88: ***ERROR Invalid expression in .WORD + 88 .word ( test-prec.mac:89: ***ERROR Invalid expression in .WORD - 89 .word / -test-prec.mac:90: ***ERROR Invalid expression in .WORD - 90 / + 89 ( + 90 test-prec.mac:91: ***ERROR Invalid expression in .WORD - 91 .word ^px + 91 .word _,$ test-prec.mac:92: ***ERROR Invalid expression in .WORD - 92 ^px -test-prec.mac:93: ***ERROR Invalid expression in .WORD - 93 .word ^px / 256 + 92 _ + 93 000144 000000G $ test-prec.mac:94: ***ERROR Invalid expression in .WORD - 94 ^px / 256 - 95 - 96 000136 000001 000002 000003 1,2,3 - 97 000144 000000G 000000G 000000G .1,.2,.3 - 97 + 94 .word / +test-prec.mac:95: ***ERROR Invalid expression in .WORD + 95 / +test-prec.mac:96: ***ERROR Invalid expression in .WORD + 96 .word ^px +test-prec.mac:97: ***ERROR Invalid expression in .WORD + 97 ^px +test-prec.mac:98: ***ERROR Invalid expression in .WORD + 98 .word ^px / 256 +test-prec.mac:99: ***ERROR Invalid expression in .WORD + 99 ^px / 256 + 100 + 101 000146 000001 000002 000003 1,2,3 + 102 000154 000000G 000000G 000000G .1,.2,.3 + 102 Symbol table -$ = ****** GX .1 = ****** GX .3 = ****** GX -. ******R 001 .2 = ****** GX NAME = ****** G +$ = ****** GX .1 = ****** GX .3 = ****** GX FIVE = 000005 +. ******R 001 .2 = ****** GX A 000030R 001 NAME = ****** G Program sections: . ABS. 000000 000 (RW,I,GBL,ABS,OVR,NOSAV) - 000152 001 (RW,I,LCL,REL,CON,NOSAV) + 000162 001 (RW,I,LCL,REL,CON,NOSAV) diff --git a/tests/test-prec.mac b/tests/test-prec.mac index cb9d36e..6ef75ea 100644 --- a/tests/test-prec.mac +++ b/tests/test-prec.mac @@ -20,6 +20,11 @@ .word 12. / 4 ; 000003 .word 123 & 771 ; 000121 .word 123121 ! 322 ; 123323 +five = 5 +a: .word 123 _ 3 ; 001230 + .word five _ 6 ; 000500 + .word 101_five ; 004040 + .word a _ 3 ; Invalid expression .word - 377 ; 177401 .word + 377 ; 000377