diff options
| author | Cliff Click <cliffc@acm.org> | 2024-11-13 20:53:05 -0800 |
|---|---|---|
| committer | Cliff Click <cliffc@acm.org> | 2024-11-23 09:03:20 -0800 |
| commit | 477c71d89d107936cd0c4776bb2d5ff37cb91539 (patch) | |
| tree | d2f4dcec5620a757b44615c0db515e5142900f49 | |
| parent | 3652f49f679de25a2544225d6a3600a63b693ba0 (diff) | |
| download | Simple-477c71d89d107936cd0c4776bb2d5ff37cb91539.tar.gz Simple-477c71d89d107936cd0c4776bb2d5ff37cb91539.zip | |
Allow oper-assign, += -= etc
| -rw-r--r-- | chapter17/README.md | 14 | ||||
| -rw-r--r-- | chapter17/src/main/java/com/seaofnodes/simple/Parser.java | 49 | ||||
| -rw-r--r-- | chapter17/src/test/java/com/seaofnodes/simple/Chapter17Test.java | 22 |
3 files changed, 64 insertions, 21 deletions
diff --git a/chapter17/README.md b/chapter17/README.md index 1bac940b..d65ff879 100644 --- a/chapter17/README.md +++ b/chapter17/README.md @@ -12,6 +12,14 @@ Also allows `s.fld++` and `ary[idx]++`, and their `--` variants. Allow pre-increment for identifiers only, for now: `--pc`. +## Operator assignment + +Along the same lines as post-increment, we now allow `op=` assignment +with semantics similar to other languages. + +`x += y` + + ## var & val `var` can be used in the `type` position to indicate a "variable" (mutable @@ -125,11 +133,5 @@ return i; // ERROR: Undefined name 'i' -oper-assign +=, -= TODO switch - - - - - diff --git a/chapter17/src/main/java/com/seaofnodes/simple/Parser.java b/chapter17/src/main/java/com/seaofnodes/simple/Parser.java index 09ea21ac..47e7c3bb 100644 --- a/chapter17/src/main/java/com/seaofnodes/simple/Parser.java +++ b/chapter17/src/main/java/com/seaofnodes/simple/Parser.java @@ -889,13 +889,30 @@ public class Parser { if( matchx("new" ) ) return alloc(); // Expect an identifier now ScopeMinNode.Var n = requireLookupId("an identifier or expression"); - Node rvalue = _scope.in(n).keep(); - if( matchx("++") || matchx("--") ) { - if( n._final ) - throw error("Cannot reassign final '"+n._name+"'"); - _scope.update(n,zsMask(peep(new AddNode(rvalue,con( _lexer.peek(-1)=='+' ? 1 : -1))),n.type())); - } - return rvalue.unkeep(); + Node rvalue = _scope.in(n); + // Check for assign-update, x += e0; + char ch = _lexer.matchOperAssign(); + if( ch==0 ) return rvalue; + if( n._final ) + throw error("Cannot reassign final '"+n._name+"'"); + Node op = switch(ch) { + case '+' -> new AddNode(rvalue,null); + case '-' -> new SubNode(rvalue,null); + case '*' -> new MulNode(rvalue,null); + case '/' -> new DivNode(rvalue,null); + case 1 -> new AddNode(rvalue,con( 1)); + case (char)-1 -> new AddNode(rvalue,con(-1)); + default -> throw Utils.TODO(); + }; + // Return pre-value (x+=1) or post-value (x++) + boolean pre = op.in(2)==null; + // Parse RHS argument as needed + if( pre ) + { op.keep().setDef(2,parseExpression()); op.unkeep(); } + else rvalue.keep(); // Keep post-value across peeps + op = zsMask(peep(op),n.type()); + _scope.update(n,op); + return pre ? op : rvalue.unkeep(); } ScopeMinNode.Var requireLookupId(String msg) { @@ -1344,12 +1361,28 @@ public class Parser { // private boolean isPunctuation(char ch) { - return "=;[]<>()+-/*".indexOf(ch) != -1; + return "=;[]<>()+-/*&|^".indexOf(ch) != -1; } private String parsePunctuation() { int start = _position; return new String(_input, start, 1); } + + // Next oper= character, or 0. + // As a convenience, mark "++" as a char 1 and "--" as char -1 (65535) + public char matchOperAssign() { + skipWhiteSpace(); + if( _position+2 >= _input.length ) return 0; + char ch0 = (char)_input[_position]; + if( "+-/*&|^".indexOf(ch0) == -1 ) return 0; + char ch1 = (char)_input[_position+1]; + if( ch1=='=' ) + { _position += 2; return ch0; } + if( isIdLetter((char)_input[_position+2]) ) return 0; // Stop --x + if( ch0 == '+' && ch1 == '+' ) { _position += 2; return (char) 1; } + if( ch0 == '-' && ch1 == '-' ) { _position += 2; return (char)-1; } + return 0; + } } } diff --git a/chapter17/src/test/java/com/seaofnodes/simple/Chapter17Test.java b/chapter17/src/test/java/com/seaofnodes/simple/Chapter17Test.java index b1f7eb43..176a9236 100644 --- a/chapter17/src/test/java/com/seaofnodes/simple/Chapter17Test.java +++ b/chapter17/src/test/java/com/seaofnodes/simple/Chapter17Test.java @@ -105,6 +105,14 @@ return s.x; assertEquals(255L, Evaluator.evaluate(stop, 0)); } + @Test + public void testInc8() { + Parser parser = new Parser("int x; x+=2; return x+=3;"); + StopNode stop = parser.parse().iterate(); + assertEquals("return 5;", stop.toString()); + assertEquals(5L, Evaluator.evaluate(stop, 0)); + } + // --------------------------------------------------------------- @Test public void testVar0() { Parser parser = new Parser("var d; return d;"); @@ -288,7 +296,7 @@ return b ? b.next ? b.next.x : b.x; // parses "b ? (b.next ? b.next.x : b.x) : 0 Parser parser = new Parser(""" int sum=0; for( int i=0; i<arg; i++ ) - sum = sum + i; + sum += i; return sum; """); StopNode stop = parser.parse().iterate(); @@ -301,7 +309,7 @@ return sum; Parser parser = new Parser(""" int sum=0, i=0; for( ; i<arg; i++ ) - sum = sum + i; + sum += i; return sum; """); StopNode stop = parser.parse().iterate(); @@ -315,7 +323,7 @@ return sum; int sum=0; for( int i=0; ; i++ ) { if( i>=arg ) break; - sum = sum + i; + sum += i; } return sum; """); @@ -329,7 +337,7 @@ return sum; Parser parser = new Parser(""" int sum=0; for( int i=0; i<arg; ) - sum = sum + i++; + sum += i++; return sum; """); StopNode stop = parser.parse().iterate(); @@ -342,7 +350,7 @@ return sum; Parser parser = new Parser(""" int sum=0; for( int i=0; i<arg; i++ ) - sum = sum + i; + sum += i; return i; """); try { parser.parse().iterate(); fail(); } @@ -361,7 +369,7 @@ while( arg-- ) int sum=0; var ptr = head; // A read-only ptr, to be assigned from read-only next fields for( ; ptr; ptr = ptr.next ) - sum = sum + ptr.i; + sum += ptr.i; return sum; """); StopNode stop = parser.parse().iterate(); @@ -382,7 +390,7 @@ for( p=2; p*p < arg; p++ ) { // p is now a prime primes[nprimes++] = p; // Mark out the rest non-primes - for( int i = p + p; i < ary#; i = i + p ) + for( int i = p + p; i < ary#; i += p ) ary[i] = true; } // Now just collect the remaining primes, no more marking |
