diff options
Diffstat (limited to 'parser')
| -rw-r--r-- | parser/decl.go | 2 | ||||
| -rw-r--r-- | parser/expr.go | 31 | ||||
| -rw-r--r-- | parser/parse.go | 45 | ||||
| -rw-r--r-- | parser/tokens.go | 26 |
4 files changed, 61 insertions, 43 deletions
diff --git a/parser/decl.go b/parser/decl.go index 807fd72..378eb56 100644 --- a/parser/decl.go +++ b/parser/decl.go @@ -358,7 +358,7 @@ func (p *Parser) parseVarLine(in Tokens) (out Tokens, err error) { } out = append(out, newIdent(vars[i], 0)) out = append(out, v...) - out = append(out, newToken(lang.Assign, 0)) + out = append(out, newToken(lang.Assign, "", 0)) } return out, err } diff --git a/parser/expr.go b/parser/expr.go index 835ae28..f180c1f 100644 --- a/parser/expr.go +++ b/parser/expr.go @@ -82,14 +82,14 @@ func (p *Parser) parseExpr(in Tokens, typeStr string) (out Tokens, err error) { addop(t) xp := strconv.Itoa(p.labelCount[p.scope]) p.labelCount[p.scope]++ - out = append(out, Token{Token: scanner.Token{Tok: lang.JumpSetFalse, Str: p.scope + "x" + xp}}) + out = append(out, newJumpSetFalse(p.scope+"x"+xp, t.Pos)) ops[len(ops)-1].Str = p.scope + "x" + xp case lang.Lor: addop(t) xp := strconv.Itoa(p.labelCount[p.scope]) p.labelCount[p.scope]++ - out = append(out, Token{Token: scanner.Token{Tok: lang.JumpSetTrue, Str: p.scope + "x" + xp}}) + out = append(out, newJumpSetTrue(p.scope+"x"+xp, t.Pos)) ops[len(ops)-1].Str = p.scope + "x" + xp case lang.Ident: @@ -114,12 +114,12 @@ func (p *Parser) parseExpr(in Tokens, typeStr string) (out Tokens, err error) { if i == 0 || in[i-1].Tok.IsOperator() { out = append(out, toks...) } else { - prec := p.precedence(Token{Token: scanner.Token{Tok: lang.Call}}) + prec := p.precedence(newCall(0)) for len(ops) > 0 && prec < p.precedence(ops[len(ops)-1]) { out = append(out, popop()) } // func call: ensure that the func token in on the top of the stack, after args. - ops = append(ops, Token{Token: scanner.Token{Tok: lang.Call, Pos: t.Pos, Beg: p.numItems(t.Block(), lang.Comma)}}) + ops = append(ops, newCall(t.Pos, p.numItems(t.Block(), lang.Comma))) out = append(out, toks...) } @@ -129,14 +129,14 @@ func (p *Parser) parseExpr(in Tokens, typeStr string) (out Tokens, err error) { typ := p.Symbols[typeStr].Type.Elem() ctype = typ.String() p.Symbols.Add(symbol.UnsetAddr, ctype, vm.NewValue(typ), symbol.Type, typ, p.funcScope != "") - out = append(out, Token{Token: scanner.Token{Tok: lang.Ident, Pos: t.Pos, Str: ctype}}) + out = append(out, newIdent(ctype, t.Pos)) } toks, err := p.parseComposite(t.Block(), ctype) out = append(out, toks...) if err != nil { return out, err } - ops = append(ops, Token{Token: scanner.Token{Tok: lang.Composite, Pos: t.Pos, Str: ctype}}) + ops = append(ops, newComposite(t.Pos)) case lang.BracketBlock: if i == 0 || in[i-1].Tok.IsOperator() { @@ -148,7 +148,7 @@ func (p *Parser) parseExpr(in Tokens, typeStr string) (out Tokens, err error) { ctype = typ.String() // p.Symbols.Add(symbol.UnsetAddr, ctype, vm.NewValue(typ), symbol.Type, typ, p.funcScope != "") p.Symbols.Add(symbol.UnsetAddr, ctype, vm.NewValue(typ), symbol.Type, typ, false) - out = append(out, Token{Token: scanner.Token{Tok: lang.Ident, Pos: t.Pos, Str: ctype}}) + out = append(out, newIdent(ctype, t.Pos)) i += n - 1 break } @@ -163,10 +163,10 @@ func (p *Parser) parseExpr(in Tokens, typeStr string) (out Tokens, err error) { if i < len(in)-2 && in[i+1].Tok == lang.Assign { // A bracket block followed by assign implies an IndexAssign token, // as assignement to a map element cannot be implemented through a normal Assign. - ops = append(ops, Token{Token: scanner.Token{Tok: lang.IndexAssign, Pos: t.Pos}}) + ops = append(ops, newIndexAssign(t.Pos)) i++ } else if toks[len(toks)-1].Tok != lang.Slice { - ops = append(ops, Token{Token: scanner.Token{Tok: lang.Index, Pos: t.Pos}}) + ops = append(ops, newIndex(t.Pos)) } case lang.Struct: @@ -176,6 +176,7 @@ func (p *Parser) parseExpr(in Tokens, typeStr string) (out Tokens, err error) { } ctype = typ.String() p.Symbols.Add(symbol.UnsetAddr, ctype, vm.NewValue(typ), symbol.Type, typ, p.funcScope != "") + // out = append(out, Token{Token: scanner.Token{Tok: lang.Ident, Pos: t.Pos, Str: ctype}}) out = append(out, Token{Token: scanner.Token{Tok: lang.Ident, Pos: t.Pos, Str: ctype}}) i++ @@ -186,7 +187,7 @@ func (p *Parser) parseExpr(in Tokens, typeStr string) (out Tokens, err error) { } ctype = typ.String() p.Symbols.Add(symbol.UnsetAddr, ctype, vm.NewValue(typ), symbol.Type, typ, p.funcScope != "") - out = append(out, Token{Token: scanner.Token{Tok: lang.Ident, Pos: t.Pos, Str: ctype}}) + out = append(out, newIdent(ctype, t.Pos)) i += n - 1 case lang.Comment: @@ -218,9 +219,9 @@ func (p *Parser) parseComposite(s, typ string) (Tokens, error) { } if noColon { // Insert a numeric index key and a colon operator. - result = append(result, Token{Token: scanner.Token{Tok: lang.Int, Str: strconv.Itoa(i)}}) + result = append(result, newInt(i, toks[0].Pos)) result = append(result, toks...) - result = append(result, Token{Token: scanner.Token{Tok: lang.Colon, Str: ":"}}) + result = append(result, newColon(toks[0].Pos)) sliceLen++ } else { result = append(result, toks...) @@ -245,12 +246,12 @@ func (p *Parser) parseBlock(t Token, typ string) (result Tokens, err error) { } if len(sub) == 0 { if i == 0 { - result = append(result, Token{Token: scanner.Token{Tok: lang.Int, Str: "0"}}) + result = append(result, newInt(0, tokens[0].Pos)) continue } else if i == 2 { return nil, errors.New("final index required in 3-index slice") } - result = append(result, Token{Token: scanner.Token{Tok: lang.Len, Beg: 1}}) + result = append(result, newLen(1, tokens[0].Pos)) continue } toks, err := p.parseExpr(sub, typ) @@ -259,7 +260,7 @@ func (p *Parser) parseBlock(t Token, typ string) (result Tokens, err error) { } result = append(result, toks...) } - result = append(result, Token{Token: scanner.Token{Tok: lang.Slice, Pos: t.Pos}}) + result = append(result, newSlice(t.Pos)) return result, err } diff --git a/parser/parse.go b/parser/parse.go index 89163cf..95179be 100644 --- a/parser/parse.go +++ b/parser/parse.go @@ -168,7 +168,7 @@ func (p *Parser) parseBreak(in Tokens) (out Tokens, err error) { default: return nil, ErrBreak } - out = Tokens{{Token: scanner.Token{Tok: lang.Goto, Str: label}}} + out = append(out, newGoto(label, in[0].Pos)) return out, err } @@ -186,7 +186,7 @@ func (p *Parser) parseContinue(in Tokens) (out Tokens, err error) { default: return nil, ErrContinue } - out = Tokens{{Token: scanner.Token{Tok: lang.Goto, Str: label}}} + out = append(out, newGoto(label, in[0].Pos)) return out, err } @@ -195,7 +195,7 @@ func (p *Parser) parseGoto(in Tokens) (out Tokens, err error) { return nil, ErrGoto } // TODO: check validity of user provided label - return Tokens{{Token: scanner.Token{Tok: lang.Goto, Str: p.funcScope + "/" + in[1].Str}}}, nil + return Tokens{newGoto(p.funcScope+"/"+in[1].Str, in[0].Pos)}, nil } func (p *Parser) parseFor(in Tokens) (out Tokens, err error) { @@ -231,13 +231,13 @@ func (p *Parser) parseFor(in Tokens) (out Tokens, err error) { } out = init } - out = append(out, Token{Token: scanner.Token{Tok: lang.Label, Str: p.scope + "b"}}) + out = append(out, newLabel(p.scope+"b", in[0].Pos)) if len(cond) > 0 { if cond, err = p.parseExpr(cond, ""); err != nil { return nil, err } out = append(out, cond...) - out = append(out, Token{Token: scanner.Token{Tok: lang.JumpFalse, Str: p.scope + "e"}}) + out = append(out, newJumpFalse(p.scope+"e", in[0].Pos)) } if body, err = p.Parse(in[len(in)-1].Block()); err != nil { return nil, err @@ -250,8 +250,9 @@ func (p *Parser) parseFor(in Tokens) (out Tokens, err error) { out = append(out, post...) } out = append(out, - Token{Token: scanner.Token{Tok: lang.Goto, Str: p.scope + "b"}}, - Token{Token: scanner.Token{Tok: lang.Label, Str: p.scope + "e"}}) + newGoto(p.scope+"b", in[0].Pos), + newLabel(p.scope+"e", in[0].Pos), + ) out = append(out, final...) return out, err } @@ -287,8 +288,8 @@ func (p *Parser) parseFunc(in Tokens) (out Tokens, err error) { }() out = Tokens{ - {Token: scanner.Token{Tok: lang.Goto, Str: fname + "_end"}}, // Skip function definition. - {Token: scanner.Token{Tok: lang.Label, Pos: in[0].Pos, Str: fname}}, + newGoto(fname+"_end", in[0].Pos), // Skuo function definition. + newLabel(fname, in[0].Pos), } bi := in.Index(lang.BraceBlock) @@ -308,7 +309,7 @@ func (p *Parser) parseFunc(in Tokens) (out Tokens, err error) { return out, err } if l := p.framelen[p.funcScope] - 1; l > 0 { - out = append(out, Token{Token: scanner.Token{Tok: lang.Grow, Beg: l}}) + out = append(out, newGrow(l, in[0].Pos)) } out = append(out, toks...) if out[len(out)-1].Tok != lang.Return { @@ -320,7 +321,7 @@ func (p *Parser) parseFunc(in Tokens) (out Tokens, err error) { } out = append(out, x...) } - out = append(out, Token{Token: scanner.Token{Tok: lang.Label, Str: fname + "_end"}}) + out = append(out, newLabel(fname+"_end", in[0].Pos)) return out, err } @@ -341,9 +342,9 @@ func (p *Parser) parseIf(in Tokens) (out Tokens, err error) { return nil, err } if sc > 0 { - pre = append(pre, Token{Token: scanner.Token{Tok: lang.Goto, Str: p.scope + "e0"}}) + pre = append(pre, newGoto(p.scope+"e0", in[i].Pos)) } - pre = append(pre, Token{Token: scanner.Token{Tok: lang.Label, Str: p.scope + "e" + ssc}}) + pre = append(pre, newLabel(p.scope+"e"+ssc, in[i].Pos)) out = append(pre, out...) i-- @@ -371,7 +372,7 @@ func (p *Parser) parseIf(in Tokens) (out Tokens, err error) { return nil, err } pre = append(pre, cond...) - pre = append(pre, Token{Token: scanner.Token{Tok: lang.JumpFalse, Str: p.scope + "e" + ssc}}) + pre = append(pre, newJumpFalse(p.scope+"e"+ssc, in[i].Pos)) out = append(pre, out...) i = ifp if i > 1 && in[i].Tok == lang.If && in[i-1].Tok == lang.Else { // Step over 'else if'. @@ -433,12 +434,12 @@ func (p *Parser) parseSwitch(in Tokens) (out Tokens, err error) { } out = append(out, co...) } - out = append(out, Token{Token: scanner.Token{Tok: lang.Label, Str: p.breakLabel}}) + out = append(out, newLabel(p.breakLabel, in[len(in)-1].Pos)) return out, err } func (p *Parser) parseCaseClause(in Tokens, index, maximum int, condSwitch bool) (out Tokens, err error) { - in = append(in, Token{Token: scanner.Token{Tok: lang.Semicolon}}) // Force a ';' at the end of body clause. + in = append(in, newSemicolon(in[len(in)-1].Pos)) // Force a ';' at the end of body clause. var conds, body Tokens tl := in.Split(lang.Colon) if len(tl) != 2 { @@ -464,24 +465,24 @@ func (p *Parser) parseCaseClause(in Tokens, index, maximum int, condSwitch bool) } else { next = fmt.Sprintf("%sc%d.%d", p.scope, index, i+1) } - out = append(out, Token{Token: scanner.Token{Tok: lang.Label, Str: txt}}) + out = append(out, newLabel(txt, 0)) // FIXME: fix label position if len(cond) > 0 { out = append(out, cond...) if condSwitch { - out = append(out, Token{Token: scanner.Token{Tok: lang.EqualSet}}) + out = append(out, newEqualSet(cond[0].Pos)) } - out = append(out, Token{Token: scanner.Token{Tok: lang.JumpFalse, Str: next}}) + out = append(out, newJumpFalse(next, cond[len(cond)-1].Pos)) } out = append(out, body...) if i != len(lcond)-1 || index != maximum { - out = append(out, Token{Token: scanner.Token{Tok: lang.Goto, Str: p.scope + "e"}}) + out = append(out, newGoto(p.scope+"e", 0)) // FIXME: fix goto position } } return out, err } func (p *Parser) parseLabel(in Tokens) (out Tokens, err error) { - return Tokens{{Token: scanner.Token{Tok: lang.Label, Str: p.funcScope + "/" + in[0].Str}}}, nil + return Tokens{newLabel(p.funcScope+"/"+in[0].Str, in[0].Pos)}, nil } func (p *Parser) parseReturn(in Tokens) (out Tokens, err error) { @@ -490,7 +491,7 @@ func (p *Parser) parseReturn(in Tokens) (out Tokens, err error) { return out, err } } else if l == 0 { - in = Tokens{{Token: scanner.Token{Tok: lang.Return}}} // Implicit return in functions with no return parameters. + in = Tokens{newReturn(0)} // Implicit return in functions with no return parameters. } // TODO: the function symbol should be already present in the parser context. diff --git a/parser/tokens.go b/parser/tokens.go index 9ae655b..a0a93fa 100644 --- a/parser/tokens.go +++ b/parser/tokens.go @@ -1,6 +1,7 @@ package parser import ( + "strconv" "strings" "github.com/mvertes/parscan/lang" @@ -69,10 +70,25 @@ func (toks Tokens) SplitStart(tok lang.Token) (result []Tokens) { } } -func newIdent(name string, pos int, arg ...any) Token { - return Token{Token: scanner.Token{Tok: lang.Ident, Pos: pos, Str: name}, Arg: arg} +func newToken(tok lang.Token, str string, pos int, arg ...any) Token { + return Token{Token: scanner.Token{Tok: tok, Str: str, Pos: pos}, Arg: arg} } -func newToken(tok lang.Token, pos int, arg ...any) Token { - return Token{Token: scanner.Token{Tok: tok, Pos: pos}, Arg: arg} -} +func newIdent(name string, pos int, arg ...any) Token { return newToken(lang.Ident, name, pos, arg...) } +func newCall(pos int, arg ...any) Token { return newToken(lang.Call, "", pos, arg...) } +func newGoto(label string, pos int) Token { return newToken(lang.Goto, label, pos) } +func newLabel(label string, pos int) Token { return newToken(lang.Label, label, pos) } +func newJumpFalse(label string, pos int) Token { return newToken(lang.JumpFalse, label, pos) } +func newGrow(size, pos int) Token { return newToken(lang.Grow, "", pos, size) } +func newSemicolon(pos int) Token { return newToken(lang.Semicolon, "", pos) } +func newEqualSet(pos int) Token { return newToken(lang.EqualSet, "", pos) } +func newReturn(pos int) Token { return newToken(lang.Return, "", pos) } +func newJumpSetFalse(label string, pos int) Token { return newToken(lang.JumpSetFalse, label, pos) } +func newJumpSetTrue(label string, pos int) Token { return newToken(lang.JumpSetTrue, label, pos) } +func newComposite(pos int) Token { return newToken(lang.Composite, "", pos) } +func newIndexAssign(pos int) Token { return newToken(lang.IndexAssign, "", pos) } +func newIndex(pos int) Token { return newToken(lang.Index, "", pos) } +func newInt(i, pos int) Token { return newToken(lang.Int, strconv.Itoa(i), pos) } +func newColon(pos int) Token { return newToken(lang.Colon, "", pos) } +func newLen(i, pos int) Token { return newToken(lang.Len, "", pos, i) } +func newSlice(pos int) Token { return newToken(lang.Slice, "", pos) } |
