// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com). // All rights reserved. // parser.go package expr import ( "fmt" ) //-------- parser type parser struct { ctx exprContext } func NewParser(ctx exprContext) (p *parser) { p = &parser{ ctx: ctx, } return p } func (self *parser) parse(scanner *scanner, termSymbols ...Symbol) (tree *ast, err error) { tree = NewAst() firstToken := true for tk := scanner.Next(); err == nil && tk != nil && !tk.IsTerm(termSymbols); tk = scanner.Next() { if tk.Sym == SymComment { continue } //fmt.Println("Token:", tk) if firstToken && (tk.Sym == SymMinus || tk.Sym == SymPlus) { if tk.Sym == SymMinus { tk.Sym = SymChangeSign } else { tk.Sym = SymUnchangeSign } } firstToken = false if tk.Sym == SymOpenRound { var subTree *ast if subTree, err = self.parse(scanner, SymClosedRound); err == nil { subTree.root.priority = priValue tree.addTerm(subTree.root) } } else if tk.Sym == SymFunction { name, _ := tk.Value.(string) funcObj := self.ctx.GetFuncInfo(name) if funcObj == nil { err = fmt.Errorf("unknown function %q", name) break } maxArgs := funcObj.MaxArgs() if maxArgs < 0 { maxArgs = funcObj.MinArgs() + 10 } args := make([]*term, 0, maxArgs) lastSym := SymUnknown for lastSym != SymClosedRound && lastSym != SymEos { var subTree *ast if subTree, err = self.parse(scanner, SymComma, SymClosedRound); err == nil { args = append(args, subTree.root) } else { break } lastSym = scanner.Previous().Sym } if err == nil { // TODO Check arguments t := newFuncTerm(tk, args) tree.addTerm(t) } } else { err = tree.addToken(tk) } } return }