From bffc031ea83c7176aac3d3828de0060c6630140c Mon Sep 17 00:00:00 2001 From: Marc Vertes Date: Tue, 6 Jan 2026 19:02:29 +0100 Subject: fix: correct and simplify parsing of expressions. The expressions were parsed from right to left, and it was incorrect and cumbersome. Now they are processed from left to right, with a simpler and correct handling of precedence rules. The vm function call syntax has been changed to set the function before the input arguments on the stack, as to follow the declaring order in languages. --- lang/golang/go.go | 180 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 110 insertions(+), 70 deletions(-) (limited to 'lang/golang/go.go') diff --git a/lang/golang/go.go b/lang/golang/go.go index 47baee2..603b256 100644 --- a/lang/golang/go.go +++ b/lang/golang/go.go @@ -53,75 +53,115 @@ var GoSpec = &lang.Spec{ "/*": lang.CharStr, "//": lang.CharStr | lang.ExcludeEnd | lang.EosValidEnd, }, - TokenProps: map[string]lang.TokenProp{ - // Block tokens (can be nested) - "{..}": {Token: lang.BraceBlock}, - "[..]": {Token: lang.BracketBlock}, - "(..)": {Token: lang.ParenBlock}, - - // String tokens (not nested) - "//..": {Token: lang.Comment}, - "/*..": {Token: lang.Comment}, - `".."`: {Token: lang.String}, - "`..`": {Token: lang.String}, - - // Separators - ",": {Token: lang.Comma}, - ";": {Token: lang.Semicolon}, - ".": {Token: lang.Period}, - ":": {Token: lang.Colon}, - - // Operators - "&": {Token: lang.And, Precedence: 1}, - "*": {Token: lang.Mul, Precedence: 1}, - "/": {Token: lang.Quo, Precedence: 1}, - "%": {Token: lang.Rem, Precedence: 1}, - "<<": {Token: lang.Shl, Precedence: 1}, - ">>": {Token: lang.Shr, Precedence: 1}, - "+": {Token: lang.Add, Precedence: 2}, - "-": {Token: lang.Sub, Precedence: 2}, - "=": {Token: lang.Assign, Precedence: 6}, - "+=": {Token: lang.AddAssign, Precedence: 6}, - "<": {Token: lang.Less, Precedence: 3}, - ">": {Token: lang.Greater, Precedence: 3}, - "^": {Token: lang.Xor, Precedence: 2}, - "~": {Token: lang.Tilde}, - "&&": {Token: lang.Land, Precedence: 4}, - "||": {Token: lang.Lor, Precedence: 5}, - ":=": {Token: lang.Define, Precedence: 6}, - "==": {Token: lang.Equal, Precedence: 3}, - "<=": {Token: lang.LessEqual, Precedence: 3}, - ">=": {Token: lang.GreaterEqual, Precedence: 3}, - "->": {Token: lang.Arrow}, - "!": {Token: lang.Not}, - "++": {Token: lang.Inc, SkipSemi: true}, - "--": {Token: lang.Dec, SkipSemi: true}, - - // Reserved keywords - "break": {Token: lang.Break}, - "case": {Token: lang.Case, SkipSemi: true}, - "chan": {Token: lang.Chan, SkipSemi: true}, - "const": {Token: lang.Const, SkipSemi: true}, - "continue": {Token: lang.Continue}, - "default": {Token: lang.Case, SkipSemi: true}, - "defer": {Token: lang.Defer, SkipSemi: true}, - "else": {Token: lang.Else, SkipSemi: true}, - "fallthrough": {Token: lang.Fallthrough}, - "for": {Token: lang.For, SkipSemi: true}, - "func": {Token: lang.Func, SkipSemi: true}, - "go": {Token: lang.Go, SkipSemi: true}, - "goto": {Token: lang.Goto, SkipSemi: true}, - "if": {Token: lang.If, SkipSemi: true}, - "import": {Token: lang.Import, SkipSemi: true}, - "interface": {Token: lang.Interface, SkipSemi: true}, - "map": {Token: lang.Map, SkipSemi: true}, - "package": {Token: lang.Package, SkipSemi: true}, - "range": {Token: lang.Range, SkipSemi: true}, - "return": {Token: lang.Return}, - "select": {Token: lang.Select, SkipSemi: true}, - "struct": {Token: lang.Struct, SkipSemi: true}, - "switch": {Token: lang.Switch, SkipSemi: true}, - "type": {Token: lang.Type, SkipSemi: true}, - "var": {Token: lang.Var, SkipSemi: true}, + Tokens: map[string]lang.Token{ + "{..}": lang.BraceBlock, + "[..]": lang.BracketBlock, + "(..)": lang.ParenBlock, + "//..": lang.Comment, + "/*..": lang.Comment, + `".."`: lang.String, + "`..`": lang.String, + ",": lang.Comma, + ";": lang.Semicolon, + ".": lang.Period, + ":": lang.Colon, + "&": lang.And, + "*": lang.Mul, + "/": lang.Quo, + "%": lang.Rem, + "<<": lang.Shl, + ">>": lang.Shr, + "+": lang.Add, + "-": lang.Sub, + "=": lang.Assign, + "+=": lang.AddAssign, + "<": lang.Less, + ">": lang.Greater, + "^": lang.Xor, + "~": lang.Tilde, + "&&": lang.Land, + "||": lang.Lor, + ":=": lang.Define, + "==": lang.Equal, + "<=": lang.LessEqual, + ">=": lang.GreaterEqual, + "->": lang.Arrow, + "!": lang.Not, + "++": lang.Inc, + "--": lang.Dec, + "break": lang.Break, + "case": lang.Case, + "chan": lang.Chan, + "const": lang.Const, + "continue": lang.Continue, + "default": lang.Case, // Consider "default" as an empty "case" clause. + "defer": lang.Defer, + "else": lang.Else, + "fallthrough": lang.Fallthrough, + "for": lang.For, + "func": lang.Func, + "go": lang.Go, + "goto": lang.Goto, + "if": lang.If, + "import": lang.Import, + "interface": lang.Interface, + "map": lang.Map, + "package": lang.Package, + "range": lang.Range, + "return": lang.Return, + "select": lang.Select, + "struct": lang.Struct, + "switch": lang.Switch, + "type": lang.Type, + "var": lang.Var, + }, + TokenProps: []lang.TokenProp{ + lang.And: {Precedence: 5}, + lang.Mul: {Precedence: 5}, + lang.Quo: {Precedence: 5}, + lang.Rem: {Precedence: 5}, + lang.Shl: {Precedence: 5}, + lang.Shr: {Precedence: 5}, + lang.Add: {Precedence: 4}, + lang.Sub: {Precedence: 4}, + lang.Xor: {Precedence: 4}, + lang.Or: {Precedence: 4}, + lang.Equal: {Precedence: 3}, + lang.LessEqual: {Precedence: 3}, + lang.GreaterEqual: {Precedence: 3}, + lang.Less: {Precedence: 3}, + lang.Greater: {Precedence: 3}, + lang.Land: {Precedence: 1}, + lang.Lor: {Precedence: 0}, + lang.Minus: {Precedence: 6}, + lang.Not: {Precedence: 6}, + lang.Call: {Precedence: 6}, + lang.Index: {Precedence: 6}, + lang.Period: {Precedence: 7}, + lang.Colon: {Precedence: 7}, + lang.Inc: {SkipSemi: true}, + lang.Dec: {SkipSemi: true}, + lang.Case: {SkipSemi: true}, + lang.Chan: {SkipSemi: true}, + lang.Const: {SkipSemi: true}, + lang.Default: {SkipSemi: true}, + lang.Defer: {SkipSemi: true}, + lang.Else: {SkipSemi: true}, + lang.For: {SkipSemi: true}, + lang.Func: {SkipSemi: true}, + lang.Go: {SkipSemi: true}, + lang.Goto: {SkipSemi: true}, + lang.If: {SkipSemi: true}, + lang.Import: {SkipSemi: true}, + lang.Interface: {SkipSemi: true}, + lang.Map: {SkipSemi: true}, + lang.Package: {SkipSemi: true}, + lang.Range: {SkipSemi: true}, + lang.Select: {SkipSemi: true}, + lang.Struct: {SkipSemi: true}, + lang.Switch: {SkipSemi: true}, + lang.Type: {SkipSemi: true}, + lang.Var: {SkipSemi: true}, + lang.MaxTok: {}, // To ensure that all Tokens have a TokenProp. }, } -- cgit v1.2.3