summaryrefslogtreecommitdiff
path: root/parser
diff options
context:
space:
mode:
Diffstat (limited to 'parser')
-rw-r--r--parser/decl.go2
-rw-r--r--parser/expr.go31
-rw-r--r--parser/parse.go45
-rw-r--r--parser/tokens.go26
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) }