summaryrefslogtreecommitdiff
path: root/parser
diff options
context:
space:
mode:
Diffstat (limited to 'parser')
-rw-r--r--parser/README.md4
-rw-r--r--parser/expr.go52
-rw-r--r--parser/parse.go27
3 files changed, 47 insertions, 36 deletions
diff --git a/parser/README.md b/parser/README.md
index ccf580d..dda3f25 100644
--- a/parser/README.md
+++ b/parser/README.md
@@ -59,7 +59,7 @@ Go language support:
- [x] iota expression
- [ ] defer statement
- [ ] recover statement
-- [ ] range clause
+- [x] range clause
- [ ] go statement
- [x] if statement (including else and else if)
- [x] for statement
@@ -80,7 +80,7 @@ Go language support:
- [x] call expressions
- [x] index expressions
- [x] selector expressions
-- [ ] slice expressions
+- [x] slice expressions
- [ ] type convertions
- [ ] type assertions
- [ ] parametric types (generic)
diff --git a/parser/expr.go b/parser/expr.go
index 1944827..149b5e2 100644
--- a/parser/expr.go
+++ b/parser/expr.go
@@ -17,9 +17,9 @@ func (p *Parser) parseExpr(in Tokens, typeStr string) (out Tokens, err error) {
var ops Tokens
var ctype string
- popop := func() (t scanner.Token) {
+ popop := func() scanner.Token {
l := len(ops) - 1
- t = ops[l]
+ t := ops[l]
ops = ops[:l]
if t.Tok.IsLogicalOp() {
t.Tok = lang.Label // Implement conditional branching directly.
@@ -27,6 +27,15 @@ func (p *Parser) parseExpr(in Tokens, typeStr string) (out Tokens, err error) {
return t
}
+ // addop adds an operator to the operator stack.
+ addop := func(t scanner.Token) {
+ // Operators on stack with a lower precedence are poped out and output first.
+ for len(ops) > 0 && p.precedence(t) < p.precedence(ops[len(ops)-1]) {
+ out = append(out, popop())
+ }
+ ops = append(ops, t)
+ }
+
lin := len(in)
for i := 0; i < lin; i++ {
switch t := in[i]; t.Tok {
@@ -47,18 +56,19 @@ func (p *Parser) parseExpr(in Tokens, typeStr string) (out Tokens, err error) {
case lang.Period:
// TODO: fail if next is not an ident.
t.Str += in[i+1].Str // Hardwire selector argument.
- for len(ops) > 0 && p.precedence(t) < p.precedence(ops[len(ops)-1]) {
- out = append(out, popop())
- }
- ops = append(ops, t)
+ addop(t)
i++ // Skip over next ident.
+ case lang.Next:
+ out = append(out, t)
+
+ case lang.Range:
+ ops = ops[:len(ops)-1] // Suppress previous assign or define.
+ addop(t)
+
case lang.Colon:
t.Str = typeStr
- for len(ops) > 0 && p.precedence(t) < p.precedence(ops[len(ops)-1]) {
- out = append(out, popop())
- }
- ops = append(ops, t)
+ addop(t)
case lang.Add, lang.And, lang.Assign, lang.Define, lang.Equal, lang.Greater, lang.Less, lang.Mul, lang.Not, lang.Sub, lang.Shl, lang.Shr:
if i == 0 || in[i-1].Tok.IsOperator() {
@@ -66,30 +76,21 @@ func (p *Parser) parseExpr(in Tokens, typeStr string) (out Tokens, err error) {
t.Tok = lang.UnaryOp[t.Tok]
// FIXME: parsetype for composite if & or *
}
- for len(ops) > 0 && p.precedence(t) < p.precedence(ops[len(ops)-1]) {
- out = append(out, popop())
- }
- ops = append(ops, t)
+ addop(t)
case lang.Land:
- for len(ops) > 0 && p.precedence(t) < p.precedence(ops[len(ops)-1]) {
- out = append(out, popop())
- }
+ addop(t)
xp := strconv.Itoa(p.labelCount[p.scope])
p.labelCount[p.scope]++
out = append(out, scanner.Token{Tok: lang.JumpSetFalse, Str: p.scope + "x" + xp})
- t.Str = p.scope + "x" + xp
- ops = append(ops, t)
+ ops[len(ops)-1].Str = p.scope + "x" + xp
case lang.Lor:
- for len(ops) > 0 && p.precedence(t) < p.precedence(ops[len(ops)-1]) {
- out = append(out, popop())
- }
+ addop(t)
xp := strconv.Itoa(p.labelCount[p.scope])
p.labelCount[p.scope]++
out = append(out, scanner.Token{Tok: lang.JumpSetTrue, Str: p.scope + "x" + xp})
- t.Str = p.scope + "x" + xp
- ops = append(ops, t)
+ ops[len(ops)-1].Str = p.scope + "x" + xp
case lang.Ident:
s, sc, ok := p.Symbols.Get(t.Str, p.scope)
@@ -145,7 +146,8 @@ func (p *Parser) parseExpr(in Tokens, typeStr string) (out Tokens, err error) {
return out, err
}
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, p.funcScope != "")
+ p.Symbols.Add(symbol.UnsetAddr, ctype, vm.NewValue(typ), symbol.Type, typ, false)
out = append(out, scanner.Token{Tok: lang.Ident, Pos: t.Pos, Str: ctype})
i += n - 1
break
diff --git a/parser/parse.go b/parser/parse.go
index 46b1724..67d8657 100644
--- a/parser/parse.go
+++ b/parser/parse.go
@@ -193,25 +193,33 @@ func (p *Parser) parseGoto(in Tokens) (out Tokens, err error) {
func (p *Parser) parseFor(in Tokens) (out Tokens, err error) {
// TODO: detect invalid code.
+ var init, cond, post, body, final Tokens
fc := strconv.Itoa(p.labelCount[p.scope])
p.labelCount[p.scope]++
- var init, cond, post, body Tokens
+ breakLabel, continueLabel := p.breakLabel, p.continueLabel
+ p.pushScope("for" + fc)
+ p.breakLabel, p.continueLabel = p.scope+"e", p.scope+"b"
+ defer func() {
+ p.breakLabel, p.continueLabel = breakLabel, continueLabel
+ p.popScope()
+ }()
pre := in[1 : len(in)-1].Split(lang.Semicolon)
switch len(pre) {
case 1:
- cond = pre[0]
+ if in.Index(lang.Range) >= 0 {
+ init = pre[0]
+ // cond = Tokens{{Tok: lang.Next, Str: p.scope + "c"}}
+ // final = Tokens{{Tok: lang.Stop, Str: p.scope + "f"}}
+ cond = Tokens{{Tok: lang.Next}}
+ final = Tokens{{Tok: lang.Stop}}
+ } else {
+ cond = pre[0]
+ }
case 3:
init, cond, post = pre[0], pre[1], pre[2]
default:
return nil, ErrFor
}
- breakLabel, continueLabel := p.breakLabel, p.continueLabel
- p.pushScope("for" + fc)
- p.breakLabel, p.continueLabel = p.scope+"e", p.scope+"b"
- defer func() {
- p.breakLabel, p.continueLabel = breakLabel, continueLabel
- p.popScope()
- }()
if len(init) > 0 {
if init, err = p.parseStmt(init); err != nil {
return nil, err
@@ -239,6 +247,7 @@ func (p *Parser) parseFor(in Tokens) (out Tokens, err error) {
out = append(out,
scanner.Token{Tok: lang.Goto, Str: p.scope + "b"},
scanner.Token{Tok: lang.Label, Str: p.scope + "e"})
+ out = append(out, final...)
return out, err
}