first working implementation of iterators and some fixes to the parser around lists analysis
This commit is contained in:
@@ -58,23 +58,72 @@ func (self *parser) parseFuncCall(scanner *scanner, allowVarRef bool, tk *Token)
|
||||
return
|
||||
}
|
||||
|
||||
// func (self *parser) parseFuncDef(scanner *scanner) (tree *term, err error) {
|
||||
// // Example: "add = func(x,y) {x+y}
|
||||
// var body *ast
|
||||
// args := make([]*term, 0)
|
||||
// tk := scanner.Next()
|
||||
// for tk.Sym != SymClosedRound && tk.Sym != SymEos {
|
||||
// if tk.Sym == SymIdentifier {
|
||||
// t := newTerm(tk, nil)
|
||||
// args = append(args, t)
|
||||
// } else {
|
||||
// err = tk.Errorf("invalid param %q, variable identifier expected", tk.source)
|
||||
// break
|
||||
// }
|
||||
// tk = scanner.Next()
|
||||
// }
|
||||
// if err == nil && tk.Sym != SymClosedRound {
|
||||
// err = tk.Errorf("unterminate function params list")
|
||||
// }
|
||||
// if err == nil {
|
||||
// tk = scanner.Next()
|
||||
// if tk.Sym == SymOpenBrace {
|
||||
// body, err = self.parseGeneral(scanner, true, true, SymClosedBrace)
|
||||
// }
|
||||
// }
|
||||
// if err == nil {
|
||||
// // TODO Check arguments
|
||||
// if scanner.Previous().Sym != SymClosedBrace {
|
||||
// err = scanner.Previous().Errorf("not properly terminated function body")
|
||||
// } else {
|
||||
// tk = scanner.makeValueToken(SymExpression, "", body)
|
||||
// tree = newFuncDefTerm(tk, args)
|
||||
// }
|
||||
// }
|
||||
// return
|
||||
// }
|
||||
|
||||
func (self *parser) parseFuncDef(scanner *scanner) (tree *term, err error) {
|
||||
// Example: "add = func(x,y) {x+y}
|
||||
var body *ast
|
||||
args := make([]*term, 0)
|
||||
tk := scanner.Next()
|
||||
for tk.Sym != SymClosedRound && tk.Sym != SymEos {
|
||||
if tk.Sym == SymIdentifier {
|
||||
t := newTerm(tk, nil)
|
||||
args = append(args, t)
|
||||
lastSym := SymUnknown
|
||||
itemExpected := false
|
||||
tk := scanner.Previous()
|
||||
for lastSym != SymClosedRound && lastSym != SymEos {
|
||||
var subTree *ast
|
||||
if subTree, err = self.parseItem(scanner, true, SymComma, SymClosedRound); err == nil {
|
||||
if subTree.root != nil {
|
||||
if subTree.root.symbol() == SymIdentifier {
|
||||
args = append(args, subTree.root)
|
||||
} else {
|
||||
err = tk.Errorf("exptected identifier, got %q", subTree.root)
|
||||
}
|
||||
} else if itemExpected {
|
||||
prev := scanner.Previous()
|
||||
err = prev.Errorf("expected function parameter, got %q", prev)
|
||||
break
|
||||
}
|
||||
} else {
|
||||
err = tk.Errorf("invalid param %q, variable identifier expected", tk.source)
|
||||
break
|
||||
}
|
||||
tk = scanner.Next()
|
||||
lastSym = scanner.Previous().Sym
|
||||
itemExpected = lastSym == SymComma
|
||||
}
|
||||
if err == nil && tk.Sym != SymClosedRound {
|
||||
err = tk.Errorf("unterminate function params list")
|
||||
|
||||
if err == nil && lastSym != SymClosedRound {
|
||||
err = tk.Errorf("unterminated function parameters list")
|
||||
}
|
||||
if err == nil {
|
||||
tk = scanner.Next()
|
||||
@@ -125,6 +174,51 @@ func (self *parser) parseList(scanner *scanner, allowVarRef bool) (subtree *term
|
||||
return
|
||||
}
|
||||
|
||||
func (self *parser) parseIterDef(scanner *scanner, allowVarRef bool) (subtree *term, err error) {
|
||||
var ds *term
|
||||
tk := scanner.Previous()
|
||||
args := make([]*term, 0)
|
||||
lastSym := SymUnknown
|
||||
dsExpected := true
|
||||
itemExpected := false
|
||||
for lastSym != SymClosedRound && lastSym != SymEos {
|
||||
var subTree *ast
|
||||
if subTree, err = self.parseItem(scanner, allowVarRef, SymComma, SymClosedRound); err == nil {
|
||||
if subTree.root != nil {
|
||||
if dsExpected {
|
||||
if sym := subTree.root.symbol(); sym == SymDict || sym == SymIdentifier {
|
||||
ds = subTree.root
|
||||
} else {
|
||||
err = subTree.root.Errorf("data-source dictionary expected, got %q", subTree.root.source())
|
||||
}
|
||||
dsExpected = false
|
||||
} else {
|
||||
args = append(args, subTree.root)
|
||||
}
|
||||
} else if itemExpected {
|
||||
prev := scanner.Previous()
|
||||
err = prev.Errorf("expected iterator argument, got %q", prev)
|
||||
break
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
lastSym = scanner.Previous().Sym
|
||||
itemExpected = lastSym == SymComma
|
||||
}
|
||||
if err == nil {
|
||||
// TODO Check arguments
|
||||
if lastSym != SymClosedRound {
|
||||
err = scanner.Previous().Errorf("unterminate iterator param list")
|
||||
} else if ds != nil {
|
||||
subtree = newIteratorTerm(tk, ds, args)
|
||||
} else {
|
||||
tk.Errorf("missing data-source param")
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (self *parser) parseDictKey(scanner *scanner, allowVarRef bool) (key any, err error) {
|
||||
tk := scanner.Next()
|
||||
if tk.Sym == SymError {
|
||||
@@ -156,9 +250,12 @@ func (self *parser) parseDictionary(scanner *scanner, allowVarRef bool) (subtree
|
||||
var key any
|
||||
if key, err = self.parseDictKey(scanner, allowVarRef); err != nil {
|
||||
break
|
||||
} else if key == nil && itemExpected {
|
||||
} else if key == nil {
|
||||
tk := scanner.Previous()
|
||||
err = tk.Errorf("expected dictionary key, got %q", tk)
|
||||
lastSym = tk.Sym
|
||||
if itemExpected {
|
||||
err = tk.Errorf("expected dictionary key, got %q", tk)
|
||||
}
|
||||
break
|
||||
}
|
||||
if subTree, err = self.parseItem(scanner, allowVarRef, SymComma, SymClosedBrace); err == nil {
|
||||
@@ -178,7 +275,7 @@ func (self *parser) parseDictionary(scanner *scanner, allowVarRef bool) (subtree
|
||||
if err == nil {
|
||||
// TODO Check arguments
|
||||
if lastSym != SymClosedBrace {
|
||||
err = scanner.Previous().Errorf("unterminate dictionary")
|
||||
err = scanner.Previous().Errorf("unterminated dictionary")
|
||||
} else {
|
||||
subtree = newDictTerm(args)
|
||||
}
|
||||
@@ -324,6 +421,12 @@ func (self *parser) parseGeneral(scanner *scanner, allowForest bool, allowVarRef
|
||||
err = tree.addTerm(funcDefTerm)
|
||||
currentTerm = funcDefTerm
|
||||
}
|
||||
case SymDollarRound:
|
||||
var iterDefTerm *term
|
||||
if iterDefTerm, err = self.parseIterDef(scanner, allowVarRef); err == nil {
|
||||
err = tree.addTerm(iterDefTerm)
|
||||
currentTerm = iterDefTerm
|
||||
}
|
||||
case SymIdentifier:
|
||||
if tk.source[0] == '@' && !allowVarRef {
|
||||
err = tk.Errorf("variable references are not allowed in top level expressions: %q", tk.source)
|
||||
|
||||
Reference in New Issue
Block a user