Repository: rokucommunity/brighterscript
Pull request #938 (2023-11-01 12:39:54)

Fix issue with unary expression parsing
Fixes precedence in UnaryExpression parsing. 

ported from brs fix: https://github.com/rokucommunity/brs/pull/24


Patch:
diff --git a/src/parser/Expression.ts b/src/parser/Expression.ts
index 6f049db4..1c02f7bf 100644
--- a/src/parser/Expression.ts
+++ b/src/parser/Expression.ts
@@ -829,9 +829,17 @@ export class UnaryExpression extends Expression {
     public readonly range: Range;
 
     transpile(state: BrsTranspileState) {
+        let separatingWhitespace: string;
+        if (isVariableExpression(this.right)) {
+            separatingWhitespace = this.right.name.leadingWhitespace;
+        } else if (isLiteralExpression(this.right)) {
+            separatingWhitespace = this.right.token.leadingWhitespace;
+        } else {
+            separatingWhitespace = ' ';
+        }
         return [
             state.transpileToken(this.operator),
-            ' ',
+            separatingWhitespace,
             ...this.right.transpile(state)
         ];
     }
diff --git a/src/parser/Parser.ts b/src/parser/Parser.ts
index 04095df5..0f87b90e 100644
--- a/src/parser/Parser.ts
+++ b/src/parser/Parser.ts
@@ -2359,7 +2359,12 @@ export class Parser {
 
     private prefixUnary(): Expression {
         const nextKind = this.peek().kind;
-        if (nextKind === TokenKind.Not || nextKind === TokenKind.Minus) {
+        if (nextKind === TokenKind.Not) {
+            this.current++; //advance
+            let operator = this.previous();
+            let right = this.relational();
+            return new UnaryExpression(operator, right);
+        } else if (nextKind === TokenKind.Minus || nextKind === TokenKind.Plus) {
             this.current++; //advance
             let operator = this.previous();
             let right = this.prefixUnary();


Test patch:
diff --git a/src/parser/tests/expression/UnaryExpression.spec.ts b/src/parser/tests/expression/UnaryExpression.spec.ts
new file mode 100644
index 00000000..cfa0be58
--- /dev/null
+++ b/src/parser/tests/expression/UnaryExpression.spec.ts
@@ -0,0 +1,51 @@
+import { expectZeroDiagnostics, getTestTranspile } from '../../../testHelpers.spec';
+import { rootDir } from '../../../testHelpers.spec';
+import { Program } from '../../../Program';
+
+describe('UnaryExpression', () => {
+    let program: Program;
+    const testTranspile = getTestTranspile(() => [program, rootDir]);
+    beforeEach(() => {
+        program = new Program({
+            rootDir: rootDir
+        });
+    });
+
+    it('handles advanced cases', () => {
+        const { file } = testTranspile(`
+            Sub Main()
+                x = 96
+                y = 56
+                w = 1088
+                h = 608
+                Offset(-x + 96, -y + 56, -w + 1088, -h + 608)
+                print -1000 +1000
+                foo = 5
+                if not foo = 1
+                    print "foo is not 1"
+                end if
+            End Sub
+            Sub Offset(x, y, w, h)
+                print x.toStr() + y.toStr() + w.toStr() + h.toStr()
+            End Sub
+        `, `
+            Sub Main()
+                x = 96
+                y = 56
+                w = 1088
+                h = 608
+                Offset(-x + 96, -y + 56, -w + 1088, -h + 608)
+                print -1000 + 1000
+                foo = 5
+                if not foo = 1
+                    print "foo is not 1"
+                end if
+            End Sub
+
+            Sub Offset(x, y, w, h)
+                print x.toStr() + y.toStr() + w.toStr() + h.toStr()
+            End Sub
+        `);
+        expectZeroDiagnostics(file);
+    });
+});
diff --git a/src/parser/tests/statement/ConstStatement.spec.ts b/src/parser/tests/statement/ConstStatement.spec.ts
index f8b59589..42a4817c 100644
--- a/src/parser/tests/statement/ConstStatement.spec.ts
+++ b/src/parser/tests/statement/ConstStatement.spec.ts
@@ -217,7 +217,7 @@ describe('ConstStatement', () => {
                 end sub
             `, `
                 sub main()
-                    bar = - 1
+                    bar = -1
                 end sub
             `, undefined, 'source/main.bs');
         });