diff --git a/source/compiler/codegen/expression/precedence.ts b/source/compiler/codegen/expression/precedence.ts index b10ebe3..92a2274 100644 --- a/source/compiler/codegen/expression/precedence.ts +++ b/source/compiler/codegen/expression/precedence.ts @@ -5,25 +5,26 @@ import { Panic } from "~/compiler/helper.ts"; const precedence = { ".": 1, "->": 1, + "**": 2, "*" : 3, "/" : 3, "%" : 3, "+" : 4, "-" : 4, "<<": 5, ">>": 5, "<" : 6, ">" : 6, "<=": 6, ">=": 6, - "instanceof": 6.5, - "==": 7, "!=": 7, - "as": 7.5, - "&": 8, - "^": 9, - "|": 10, - "&&": 11, - "||": 12, + "instanceof": 7, + "==": 8, "!=": 8, + "as": 9, + "&": 10, + "^": 11, + "|": 12, + "&&": 13, + "||": 14, } as { [key: string]: number }; export function GetPrecedence (a: string, b: string) { const A = precedence[a]; const B = precedence[b]; - if (!A) Panic(`Unknown infix operation ${a}`); - if (!B) Panic(`Unknown infix operation ${a}`); + if (A === undefined) Panic(`Unknown infix operation ${a} 0x${a.charCodeAt(0).toString(16)}`); + if (B === undefined) Panic(`Unknown infix operation ${b} 0x${b.charCodeAt(0).toString(16)}`); return A !== B ? Math.min(1, Math.max(-1, A-B)) @@ -39,51 +40,68 @@ export type PrecedenceTree = Term_Expr_arg | { }; export function ApplyPrecedence(syntax: Term_Expr) { - let root: PrecedenceTree = syntax.value[0] as PrecedenceTree; + + const val_stack = new Array(); + const op_stack = new Array(); + + val_stack.push(syntax.value[0]); for (const action of syntax.value[1].value) { const op = action.value[0].value; - const arg = action.value[1] - - // First action - if (root.type !== "infix") { - root = { - type: "infix", - lhs: root, - op, - rhs: arg, - ref: ReferenceRange.union(root.ref, arg.ref) - }; - continue; - } + const arg = action.value[1]; - const p = GetPrecedence(root.op, op); - if (p > 0) { - // Transform stealing previous operand - // (1 + 2) * 3 -> (2 * 3) + 1 - root = { - type: "infix", - lhs: root.lhs, - op: root.op, - rhs: { - type: "infix", - lhs: root.rhs, - op, - rhs: arg, - ref: ReferenceRange.union(root.ref, arg.ref) - }, - ref: ReferenceRange.union(arg.ref, arg.ref) - } + const prev = op_stack.pop(); + if (prev === undefined || GetPrecedence(prev, op) < 0) { + if (prev) op_stack.push(prev); + val_stack.push(arg); + op_stack.push(op); } else { - root = { + const lhs = val_stack.pop()!; + + val_stack.push({ type: "infix", - lhs: root, + lhs: lhs, op: op, rhs: arg, - ref: ReferenceRange.union(root.ref, arg.ref) - } + ref: ReferenceRange.union(lhs.ref, arg.ref) + }); + op_stack.push(prev); } } + let root = val_stack[0]!; + for (let i=1; i {