// nextDecimalNumber64 returns the next number, which // must fit in a non-negative int64. func (p *Parser) nextDecimalNumber64() int64 { ibase, obase := p.config.Base() defer p.config.SetBase(ibase, obase) p.config.SetBase(10, obase) v, err := value.Parse(p.need(scan.Number).Text) if err != nil { p.errorf("%s", err) } var n int64 = -1 switch num := v.(type) { case value.Int: n = int64(num) case value.BigInt: // The Int64 method produces undefined results if // the value is too large, so we must check. if num.Int.Sign() < 0 || num.Int.Cmp(value.MaxBigInt63) > 0 { p.errorf("value out of range: %v", v) } n = num.Int64() } if n < 0 { p.errorf("value must be a positive integer: %v", v) } return n }
func (p *Parser) nextDecimalNumber() int { ibase, obase := p.config.Base() defer p.config.SetBase(ibase, obase) p.config.SetBase(10, obase) v, err := value.Parse(p.need(scan.Number).Text) if err != nil { p.errorf("%s", err) } num, ok := v.(value.Int) if !ok { p.errorf("value must be an integer: %v", v) } return int(num) }
// number // integer // rational // variable // '(' Expr ')' func (p *Parser) number(tok scan.Token) value.Expr { var expr value.Expr text := tok.Text switch tok.Type { case scan.Identifier: expr = p.variable(text) case scan.Number, scan.Rational: var err error expr, err = value.Parse(text) if err != nil { p.errorf("%s: %s", text, err) } case scan.LeftParen: expr = p.expr(p.next()) tok := p.next() if tok.Type != scan.RightParen { p.errorf("expected right paren, found %s", tok) } } return expr }
// number // integer // rational // string // variable // '(' Expr ')' // If the value is a string, value.Expr is nil. func (p *Parser) number(tok scan.Token) (expr value.Expr, str string) { var err error text := tok.Text switch tok.Type { case scan.Identifier: expr = p.variable(text) case scan.String: str = value.ParseString(text) case scan.Number, scan.Rational: expr, err = value.Parse(p.context.Config(), text) case scan.LeftParen: expr = p.expr(p.next()) tok := p.next() if tok.Type != scan.RightParen { p.errorf("expected right paren, found %s", tok) } } if err != nil { p.errorf("%s: %s", text, err) } return expr, str }
return value.Binary(b.left.Eval(context), b.op, b.right.Eval(context)) } // Parser stores the state for the ivy parser. type Parser struct { scanner *scan.Scanner config *config.Config fileName string lineNum int errorCount int // Number of errors. peekTok scan.Token curTok scan.Token // most recent token from scanner context *execContext } var zero, _ = value.Parse("0") // NewParser returns a new parser that will read from the scanner. // The context must have have been created by this package's NewContext function. func NewParser(conf *config.Config, fileName string, scanner *scan.Scanner, context value.Context) *Parser { return &Parser{ scanner: scanner, config: conf, fileName: fileName, context: context.(*execContext), } } func (p *Parser) next() scan.Token { tok := p.peekTok if tok.Type != scan.EOF {