summaryrefslogtreecommitdiff
path: root/parser
diff options
context:
space:
mode:
Diffstat (limited to 'parser')
-rw-r--r--parser/expr.go36
1 files changed, 34 insertions, 2 deletions
diff --git a/parser/expr.go b/parser/expr.go
index f2dbce3..1732b8d 100644
--- a/parser/expr.go
+++ b/parser/expr.go
@@ -15,6 +15,7 @@ func (p *Parser) parseExpr(in Tokens) (out Tokens, err error) {
var ops, selectors Tokens
var vl int
var selectorIndex string
+
//
// Process tokens from last to first, the goal is to reorder the tokens in
// a stack machine processing order, so it can be directly interpreted.
@@ -30,6 +31,7 @@ func (p *Parser) parseExpr(in Tokens) (out Tokens, err error) {
out = append(out, fid)
return out, err
}
+
for i := len(in) - 1; i >= 0; i-- {
t := in[i]
// temporary assumptions: binary operators, returning 1 value
@@ -48,14 +50,22 @@ func (p *Parser) parseExpr(in Tokens) (out Tokens, err error) {
}
out = append(out, t)
vl++
+
+ case lang.Colon:
+ // Make ':' a key-value operator for literal composite.
+ ops = append(ops, t)
+
case lang.Period:
t.Str += selectorIndex
selectors = append(Tokens{t}, selectors...)
continue
+
case lang.Int, lang.String:
out = append(out, t)
vl++
- case lang.Define, lang.Add, lang.Sub, lang.Assign, lang.Equal, lang.Greater, lang.Less, lang.Mul, lang.Land, lang.Lor, lang.Shl, lang.Shr, lang.Not, lang.And:
+
+ case lang.Define, lang.Add, lang.Sub, lang.Assign, lang.Equal, lang.Greater, lang.Less,
+ lang.Mul, lang.Land, lang.Lor, lang.Shl, lang.Shr, lang.Not, lang.And:
if i == 0 || in[i-1].Tok.IsOperator() {
// An operator preceded by an operator or no token is unary.
t.Tok = lang.UnaryOp[t.Tok]
@@ -71,6 +81,7 @@ func (p *Parser) parseExpr(in Tokens) (out Tokens, err error) {
if vl < 2 {
ops = append(ops, t)
}
+
case lang.ParenBlock:
// If the previous token is an arithmetic, logic or assign operator then
// this parenthesis block is an enclosed expr, otherwise a call expr.
@@ -85,9 +96,11 @@ func (p *Parser) parseExpr(in Tokens) (out Tokens, err error) {
out = append(out, t)
vl++
ops = append(ops, scanner.Token{Tok: lang.Call, Pos: t.Pos, Beg: p.numItems(t.Block(), lang.Comma)})
+
case lang.BraceBlock:
// the block can be a func body or a composite type content.
- // In both cases it is preceded by a type definition. We must determine the starting token of type def,
+ // In both cases it is preceded by a type definition.
+ // We must determine the starting token of type def,
// parse the type def, and substitute the type def by a single ident.
// TODO: handle implicit type in composite expression.
ti := p.typeStartIndex(in[:len(in)-1])
@@ -103,19 +116,24 @@ func (p *Parser) parseExpr(in Tokens) (out Tokens, err error) {
i = ti
vl += 2
ops = append(ops, scanner.Token{Tok: lang.Composite, Pos: t.Pos})
+
case lang.BracketBlock:
out = append(out, t)
vl++
ops = append(ops, scanner.Token{Tok: lang.Index, Pos: t.Pos})
+
case lang.Comment:
return out, nil
+
default:
return nil, fmt.Errorf("invalid expression: %v: %q", t.Tok, t.Str)
}
+
if len(selectors) > 0 {
out = append(out, selectors...)
selectors = nil
}
+
if lops, lout := len(ops), len(out); lops > 0 && vl > lops {
op := ops[lops-1]
ops = ops[:lops-1]
@@ -137,6 +155,7 @@ func (p *Parser) parseExpr(in Tokens) (out Tokens, err error) {
if out, err = p.parseLogical(out); err != nil {
return out, err
}
+
if l := len(out) - 1; l >= 0 && (out[l].Tok == lang.Define || out[l].Tok == lang.Assign) {
// Handle the assignment of a logical expression.
s1 := p.subExprLen(out[:l])
@@ -166,6 +185,7 @@ func (p *Parser) parseExpr(in Tokens) (out Tokens, err error) {
out2 = append(out2, toks...)
out = append(out2, out[i+1:]...)
}
+
log.Println("Final out:", out)
return out, err
}
@@ -174,6 +194,7 @@ func (p *Parser) parseExprStr(s string) (tokens Tokens, err error) {
if tokens, err = p.Scan(s, false); err != nil {
return tokens, err
}
+
var result Tokens
for _, sub := range tokens.Split(lang.Comma) {
toks, err := p.parseExpr(sub)
@@ -182,6 +203,7 @@ func (p *Parser) parseExprStr(s string) (tokens Tokens, err error) {
}
result = append(toks, result...)
}
+
return result, err
}
@@ -194,23 +216,28 @@ func (p *Parser) parseLogical(in Tokens) (out Tokens, err error) {
if l < 0 || !in[l].Tok.IsLogicalOp() {
return in, nil
}
+
xp := strconv.Itoa(p.labelCount[p.scope])
p.labelCount[p.scope]++
rhsIndex := p.subExprLen(in[:l])
+
lhs, err := p.parseLogical(in[l-rhsIndex : l])
if err != nil {
return out, err
}
+
rhs, err := p.parseLogical(in[:l-rhsIndex])
if err != nil {
return out, err
}
out = append(out, lhs...)
+
if in[l].Tok == lang.Lor {
out = append(out, scanner.Token{Tok: lang.JumpSetTrue, Str: p.scope + "x" + xp})
} else {
out = append(out, scanner.Token{Tok: lang.JumpSetFalse, Str: p.scope + "x" + xp})
}
+
out = append(out, rhs...)
out = append(out, scanner.Token{Tok: lang.Label, Str: p.scope + "x" + xp})
return out, err
@@ -220,20 +247,25 @@ func (p *Parser) parseLogical(in Tokens) (out Tokens, err error) {
func (p *Parser) subExprLen(in Tokens) int {
l := len(in) - 1
last := in[l]
+
switch last.Tok {
case lang.Int, lang.Float, lang.String, lang.Char, lang.Ident, lang.ParenBlock, lang.BracketBlock:
return 1
+
case lang.Call:
s1 := p.subExprLen(in[:l])
return 1 + s1 + p.subExprLen(in[:l-s1])
// TODO: add selector and index operators when ready
}
+
if last.Tok.IsBinaryOp() {
s1 := p.subExprLen(in[:l])
return 1 + s1 + p.subExprLen(in[:l-s1])
}
+
if last.Tok.IsUnaryOp() {
return 1 + p.subExprLen(in[:l])
}
+
return 0 // should not occur. TODO: diplay some error here.
}