Add binary operator '_' for left shift

If the command line option yus to allow the underscore character in
symbols is NOT selected, then interpret underscore as a new binary
operator meaning to do a left shift of the left side value by the
number of bit positions indicated by the right side value.  As for the
arithmetic operators, both values must be literal (numeric constants
or symbols equated to a numeric constant).
This commit is contained in:
Stephen Casner
2021-02-13 15:25:08 -08:00
committed by Rhialto The M
parent e452ac437c
commit dcdbc02b2e
6 changed files with 148 additions and 90 deletions

View File

@@ -225,6 +225,7 @@ void implicit_gbl(
case EX_DIV: case EX_DIV:
case EX_AND: case EX_AND:
case EX_OR: case EX_OR:
case EX_LSH:
implicit_gbl(value->data.child.right); implicit_gbl(value->data.child.right);
/* FALLS THROUGH */ /* FALLS THROUGH */
case EX_COM: case EX_COM:

View File

@@ -112,6 +112,14 @@ void print_tree(
print_tree(printfile, tp->data.child.right, depth + 4); print_tree(printfile, tp->data.child.right, depth + 4);
fputc('>', printfile); fputc('>', printfile);
break; 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) if (depth == 0)
@@ -150,6 +158,7 @@ void free_tree(
case EX_DIV: case EX_DIV:
case EX_AND: case EX_AND:
case EX_OR: case EX_OR:
case EX_LSH:
free_tree(tp->data.child.left); free_tree(tp->data.child.left);
free_tree(tp->data.child.right); free_tree(tp->data.child.right);
break; break;
@@ -244,6 +253,7 @@ EX_TREE *dup_tree(
case EX_DIV: case EX_DIV:
case EX_AND: case EX_AND:
case EX_OR: case EX_OR:
case EX_LSH:
res->data.child.left = dup_tree(tp->data.child.left); res->data.child.left = dup_tree(tp->data.child.left);
res->data.child.right = dup_tree(tp->data.child.right); res->data.child.right = dup_tree(tp->data.child.right);
break; break;
@@ -703,6 +713,28 @@ EX_TREE *evaluate(
res = new_ex_bin(EX_OR, left, right); res = new_ex_bin(EX_OR, left, right);
} }
break; 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: default:
fprintf(stderr, "Invalid tree\n"); fprintf(stderr, "Invalid tree\n");
return NULL; return NULL;

View File

@@ -31,7 +31,10 @@ typedef struct ex_tree {
/* Divide */ /* Divide */
EX_AND = 12, EX_AND = 12,
/* bitwise and */ /* bitwise and */
EX_OR = 13 /* bitwise or */ EX_OR = 13,
/* bitwise or */
EX_LSH = 14
/* left shift */
} type; } type;
char *cp; /* points to end of parsed expression */ char *cp; /* points to end of parsed expression */

11
parse.c
View File

@@ -596,6 +596,7 @@ int parse_float(
#define MUL_PREC 1 #define MUL_PREC 1
#define AND_PREC 1 #define AND_PREC 1
#define OR_PREC 1 #define OR_PREC 1
#define LSH_PREC 1
EX_TREE *parse_unary( EX_TREE *parse_unary(
char *cp); /* Prototype for forward calls */ char *cp); /* Prototype for forward calls */
@@ -678,6 +679,16 @@ EX_TREE *parse_binary(
leftp = tp; leftp = tp;
break; 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: default:
/* Some unknown character. Let caller decide if it's okay. */ /* Some unknown character. Let caller decide if it's okay. */

View File

@@ -20,111 +20,117 @@
20 000022 000003 .word 12. / 4 ; 000003 20 000022 000003 .word 12. / 4 ; 000003
21 000024 000121 .word 123 & 771 ; 000121 21 000024 000121 .word 123 & 771 ; 000121
22 000026 123323 .word 123121 ! 322 ; 123323 22 000026 123323 .word 123121 ! 322 ; 123323
23 23 000005 five = 5
24 000030 177401 .word - 377 ; 177401 24 000030 001230 a: .word 123 _ 3 ; 001230
25 000032 000377 .word + 377 ; 000377 25 000032 000500 .word five _ 6 ; 000500
26 26 000034 004040 .word 101_five ; 004040
27 000034 177400 .word ^C 377 ; 177400 test-prec.mac:27: ***ERROR Invalid expression
28 000036 177400 .word ^c 377 ; 177400 27 000036 000000 .word a _ 3 ; Invalid expression
29 000040 052525 .word ^B 0101010101010101 ; 052525 28
30 000042 125252 .word ^b 1010101010101010 ; 125252 29 000040 177401 .word - 377 ; 177401
31 000044 000144 .word ^d 100 ; 000144 30 000042 000377 .word + 377 ; 000377
32 000046 000144 .word 100. ; 000144 31
33 000050 000400 .word ^x 100 ; 000400 hexadecimal is an extension 32 000044 177400 .word ^C 377 ; 177400
34 000052 070254 .word ^rRAD ; 070254 up to 3 characters; no leading spaces 33 000046 177400 .word ^c 377 ; 177400
35 000054 003100 .word ^rA ; 003100 up to 3 characters 34 000050 052525 .word ^B 0101010101010101 ; 052525
36 000056 000050 .word ^r A ; 000050 up to 3 characters 35 000052 125252 .word ^b 1010101010101010 ; 125252
37 000060 000001 .word ^r A ; 000001 up to 3 characters 36 000054 000144 .word ^d 100 ; 000144
38 000062 000051 .word ^r AA ; 000051 37 000056 000144 .word 100. ; 000144
39 000064 003101 .word ^rA A ; 003101 38 000060 000400 .word ^x 100 ; 000400 hexadecimal is an extension
40 000066 003150 .word ^rAA ; 003150 39 000062 070254 .word ^rRAD ; 070254 up to 3 characters; no leading spaces
41 000070 003151 .word ^r^/AAA/ ; bracketed strings are an extension 40 000064 003100 .word ^rA ; 003100 up to 3 characters
42 000072 070254 .word ^r<RAD> ; bracketed strings are an extension 41 000066 000050 .word ^r A ; 000050 up to 3 characters
43 000074 000054 .word ^r< AD> ; bracketed strings are an extension 42 000070 000001 .word ^r A ; 000001 up to 3 characters
44 000076 000004 .word ^r< D> ; bracketed strings are an extension 43 000072 000051 .word ^r AA ; 000051
45 000100 070204 .word ^r<R D> ; bracketed strings are an extension 44 000074 003101 .word ^rA A ; 003101
46 000102 070250 .word ^r<RA > ; bracketed strings are an extension 45 000076 003150 .word ^rAA ; 003150
47 000104 157614 .word ^R50. ; 157614 there is no whitespace in between. 46 000100 003151 .word ^r^/AAA/ ; bracketed strings are an extension
48 000106 040300 .word ^f 1.5 ; 040300 47 000102 070254 .word ^r<RAD> ; bracketed strings are an extension
49 48 000104 000054 .word ^r< AD> ; bracketed strings are an extension
50 ;;;;; 49 000106 000004 .word ^r< D> ; bracketed strings are an extension
51 ; 50 000110 070204 .word ^r<R D> ; bracketed strings are an extension
52 ; Test bracketing 51 000112 070250 .word ^r<RA > ; bracketed strings are an extension
53 ; 52 000114 157614 .word ^R50. ; 157614 there is no whitespace in between.
54 000110 000007 .word 1 + < 2 * 3 > ; 1 + 6 = 7 53 000116 040300 .word ^f 1.5 ; 040300
55 000112 000007 .word 1 + ^! 2 * 3 ! ; 1 + 6 = 7 54
56 000114 000007 .word 1 + ^/ 2 * 3 / ; 1 + 6 = 7 55 ;;;;;
57 000116 000007 .word 1 + ^$ 2 * 3 $ ; 1 + 6 = 7 56 ;
test-prec.mac:58: ***ERROR Invalid expression 57 ; Test bracketing
58 000120 000003 000000 .word 1 + ^* 2 * 3 * ; Invalid expression 58 ;
59 59 000120 000007 .word 1 + < 2 * 3 > ; 1 + 6 = 7
60 ;;;;; 60 000122 000007 .word 1 + ^! 2 * 3 ! ; 1 + 6 = 7
61 ; 61 000124 000007 .word 1 + ^/ 2 * 3 / ; 1 + 6 = 7
62 ; There was an obscure bug in parse_expr(), used to evaluate 'if df', 62 000126 000007 .word 1 + ^$ 2 * 3 $ ; 1 + 6 = 7
63 ; where it could skip past the end of the line marker. test-prec.mac:63: ***ERROR Invalid expression
64 ; 63 000130 000003 000000 .word 1 + ^* 2 * 3 * ; Invalid expression
65 ; If this happened inside an expanded macro, then after that was the 64
66 ; next line... 65 ;;;;;
67 ; In other cases it might be worse. 66 ;
68 ; 67 ; There was an obscure bug in parse_expr(), used to evaluate 'if df',
69 .macro dirdef name, flags, cond 68 ; where it could skip past the end of the line marker.
70 .rad50 /.'name/ 69 ;
71 .byte flags+0, 0 70 ; If this happened inside an expanded macro, then after that was the
72 .if df cond 71 ; next line...
73 .globl opcerr 72 ; In other cases it might be worse.
74 .word opcerr 73 ;
75 .iff 74 .macro dirdef name, flags, cond
76 .globl name 75 .rad50 /.'name/
77 .word name 76 .byte flags+0, 0
78 .endc 77 .if df cond
79 .endm 78 .globl opcerr
80 79 .word opcerr
81 000124 dirdef name 80 .iff
1 000124 130461 051010 .rad50 /.name/ 81 .globl name
2 000130 000 000 .byte +0, 0 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 3 .if df
4 .globl opcerr 4 .globl opcerr
5 .word opcerr 5 .word opcerr
6 .iff 6 .iff
7 .globl name 7 .globl name
8 000132 000000G .word name 8 000142 000000G .word name
9 .endc 9 .endc
82 87
test-prec.mac:83: ***ERROR Invalid expression in .WORD test-prec.mac:88: ***ERROR Invalid expression in .WORD
83 .word ( 88 .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 $
test-prec.mac:89: ***ERROR Invalid expression in .WORD test-prec.mac:89: ***ERROR Invalid expression in .WORD
89 .word / 89 (
test-prec.mac:90: ***ERROR Invalid expression in .WORD 90
90 /
test-prec.mac:91: ***ERROR Invalid expression in .WORD test-prec.mac:91: ***ERROR Invalid expression in .WORD
91 .word ^px 91 .word _,$
test-prec.mac:92: ***ERROR Invalid expression in .WORD test-prec.mac:92: ***ERROR Invalid expression in .WORD
92 ^px 92 _
test-prec.mac:93: ***ERROR Invalid expression in .WORD 93 000144 000000G $
93 .word ^px / 256
test-prec.mac:94: ***ERROR Invalid expression in .WORD test-prec.mac:94: ***ERROR Invalid expression in .WORD
94 ^px / 256 94 .word /
95 test-prec.mac:95: ***ERROR Invalid expression in .WORD
96 000136 000001 000002 000003 1,2,3 95 /
97 000144 000000G 000000G 000000G .1,.2,.3 test-prec.mac:96: ***ERROR Invalid expression in .WORD
97 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 Symbol table
$ = ****** GX .1 = ****** GX .3 = ****** GX $ = ****** GX .1 = ****** GX .3 = ****** GX FIVE = 000005
. ******R 001 .2 = ****** GX NAME = ****** G . ******R 001 .2 = ****** GX A 000030R 001 NAME = ****** G
Program sections: Program sections:
. ABS. 000000 000 (RW,I,GBL,ABS,OVR,NOSAV) . 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)

View File

@@ -20,6 +20,11 @@
.word 12. / 4 ; 000003 .word 12. / 4 ; 000003
.word 123 & 771 ; 000121 .word 123 & 771 ; 000121
.word 123121 ! 322 ; 123323 .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 ; 177401
.word + 377 ; 000377 .word + 377 ; 000377