Skip to content

Commit

Permalink
+expr precedence swapping
Browse files Browse the repository at this point in the history
  • Loading branch information
AjaniBilby committed Sep 16, 2023
1 parent 34ddaed commit 12e26dc
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 2 deletions.
2 changes: 1 addition & 1 deletion deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@
"lock": false,
"nodeModulesDir": true,
"test": {
"include": ["tests/*"]
"include": ["tests/*", "source/*/*"]
}
}
4 changes: 3 additions & 1 deletion source/compiler/codegen/expression/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import { Instruction } from "../../../wasm/index.ts";
import { Context } from "./../context.ts";

export function CompileExpr(ctx: Context, syntax: Syntax.Term_Expr, expect?: Intrinsic) {
return CompileArg(ctx, syntax.value[0], expect);
const op = CompileArg(ctx, syntax.value[0], expect);

return op;
}


Expand Down
96 changes: 96 additions & 0 deletions source/compiler/codegen/expression/precedence.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/// <reference lib="deno.ns" />
import { assertEquals, assertThrows } from "https://deno.land/[email protected]/assert/mod.ts";

import type { Term_Expr, Term_Expr_arg, Term_Expr_infix, _Literal } from "../../../bnf/syntax.d.ts";


const precedence = {
"." : 1, "[]": 1, "->": 1,
"*" : 3, "/" : 3, "%" : 3,
"+" : 4, "-" : 4,
"<<": 5, ">>": 5,
"<" : 6, ">" : 6, "<=": 6, ">=": 6,
"instanceof": 6.5,
"==": 7, "!=": 7,
"as": 7.5,
"&": 8,
"^": 9,
"|": 10,
"&&": 11,
"||": 12,
} as { [key: string]: number };

function GetPrecedence (a: string, b: string) {
const A = precedence[a];
const B = precedence[b];
if (A == undefined && B == undefined) {
return 0;
} else if (A == B) {
return 0;
} else if (B == undefined) {
return 1;
} else if (A == undefined) {
return -1;
} else {
return Math.min(1, Math.max(-1, A-B));
}
}

export type PrecedenceTree = Term_Expr_arg | {
lhs : PrecedenceTree,
op : string,
rhs : PrecedenceTree
};

export function ApplyPrecedence(syntax: Term_Expr) {
let root = syntax.value[0] as PrecedenceTree;

for (const action of syntax.value[1].value) {
const op = action.value[0].value;
const arg = action.value[1]

// First action
if (!Array.isArray(root)) {
root = {
lhs: root,
op,
rhs: arg
};
continue;
}

const p = GetPrecedence(root[1], op);
if (p > 0) {
// Transform stealing previous operand
// (1 + 2) * 3 -> (2 * 3) + 1
root = {
lhs: {
lhs: root[2],
op,
rhs: arg
},
op: root[1],
rhs: root[0],
}

} else {
root = {
lhs: root[0],
op: root[1],
rhs: {
lhs: root[2],
op,
rhs: arg
}
}
}
}

return root;
}

Deno.test("Check precedence of two operators", () => {
assertEquals(GetPrecedence("+", "*"), 1);
assertEquals(GetPrecedence("+", "-"), 0);
assertEquals(GetPrecedence("*", "+"), -1);
});

0 comments on commit 12e26dc

Please sign in to comment.