expressions now support intger value in bin (0b), oct (0o), and hex (0x) form

This commit is contained in:
Celestino Amoroso 2024-04-17 14:15:50 +02:00
parent b6887af77a
commit 54bc759f70
3 changed files with 105 additions and 33 deletions

View File

@ -191,10 +191,11 @@ func (self *parser) Parse(scanner *scanner, termSymbols ...Symbol) (tree *ast, e
func (self *parser) parseGeneral(scanner *scanner, allowForest bool, allowVarRef bool, termSymbols ...Symbol) (tree *ast, err error) { func (self *parser) parseGeneral(scanner *scanner, allowForest bool, allowVarRef bool, termSymbols ...Symbol) (tree *ast, err error) {
var selectorTerm *term = nil var selectorTerm *term = nil
var currentTerm *term = nil var currentTerm *term = nil
var tk *Token
tree = NewAst() tree = NewAst()
firstToken := true firstToken := true
lastSym := SymUnknown lastSym := SymUnknown
for tk := scanner.Next(); err == nil && tk != nil && !tk.IsTerm(termSymbols); tk = scanner.Next() { for tk = scanner.Next(); err == nil && tk != nil && !tk.IsTerm(termSymbols); tk = scanner.Next() {
if tk.Sym == SymComment { if tk.Sym == SymComment {
continue continue
} }
@ -281,6 +282,9 @@ func (self *parser) parseGeneral(scanner *scanner, allowForest bool, allowVarRef
} }
lastSym = tk.Sym lastSym = tk.Sym
} }
if err == nil {
err = tk.Error()
}
return return
} }

View File

@ -280,62 +280,116 @@ func (self *scanner) sync(err error) error {
return err return err
} }
func isBinaryDigit(ch byte) bool {
return ch == '0' || ch == '1'
}
func isOctalDigit(ch byte) bool {
return ch >= '0' && ch <= '7'
}
func isDecimalDigit(ch byte) bool {
return ch >= '0' && ch <= '9'
}
func isHexDigit(ch byte) bool {
return (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')
}
func (self *scanner) initBase(sb *strings.Builder, currentFirstCh byte) (firstCh byte, numBase int, digitFunc func(byte) bool, err error) {
var ch byte
var digitType string
firstCh = currentFirstCh
digitFunc = isDecimalDigit
numBase = 10
if ch, err = self.peek(); err == nil {
if ch == 'b' || ch == 'B' {
numBase = 2
digitType = "binary"
self.readChar()
digitFunc = isBinaryDigit
firstCh, err = self.readChar()
} else if ch == 'o' || ch == 'O' {
numBase = 8
digitType = "octal"
self.readChar()
digitFunc = isOctalDigit
firstCh, err = self.readChar()
} else if ch == 'x' || ch == 'X' {
numBase = 16
digitType = "hex"
self.readChar()
digitFunc = isHexDigit
firstCh, err = self.readChar()
}
if err == nil && !digitFunc(firstCh) {
if len(digitType) == 0 {
digitType = "decimal"
}
err = fmt.Errorf("expected %s digit, got '%c'", digitType, firstCh)
}
} else if err == io.EOF {
err = nil
}
return
}
func (self *scanner) parseNumber(firstCh byte) (tk *Token) { func (self *scanner) parseNumber(firstCh byte) (tk *Token) {
var err error var err error
var ch byte var ch byte
var sym Symbol = SymInteger var sym Symbol = SymInteger
var value any
var sb strings.Builder var sb strings.Builder
var isDigit func(byte) bool = isDecimalDigit
var numBase = 10
for ch = firstCh; err == nil && (ch >= '0' && ch <= '9'); ch, err = self.readChar() { if firstCh == '0' {
firstCh, numBase, isDigit, err = self.initBase(&sb, firstCh)
}
for ch = firstCh; err == nil && isDigit(ch); ch, err = self.readChar() {
sb.WriteByte(ch) sb.WriteByte(ch)
} }
if ch == '.' {
sym = SymFloat if numBase == 10 {
sb.WriteByte(ch) if err == nil && ch == '.' {
ch, err = self.readChar() sym = SymFloat
if ch >= '0' && ch <= '9' { sb.WriteByte(ch)
for ; err == nil && (ch >= '0' && ch <= '9'); ch, err = self.readChar() { ch, err = self.readChar()
sb.WriteByte(ch)
}
}
}
if ch == 'e' || ch == 'E' {
sym = SymFloat
sb.WriteByte(ch)
if ch, err = self.readChar(); err == nil {
if ch == '+' || ch == '-' {
sb.WriteByte(ch)
ch, err = self.readChar()
}
if ch >= '0' && ch <= '9' { if ch >= '0' && ch <= '9' {
for ; err == nil && (ch >= '0' && ch <= '9'); ch, err = self.readChar() { for ; err == nil && (ch >= '0' && ch <= '9'); ch, err = self.readChar() {
sb.WriteByte(ch) sb.WriteByte(ch)
} }
//err = self.sync(err)
} else {
err = errors.New("expected integer exponent")
} }
} }
// } else { if err == nil && (ch == 'e' || ch == 'E') {
// err = self.sync(err) sym = SymFloat
sb.WriteByte(ch)
if ch, err = self.readChar(); err == nil {
if ch == '+' || ch == '-' {
sb.WriteByte(ch)
ch, err = self.readChar()
}
if ch >= '0' && ch <= '9' {
for ; err == nil && (ch >= '0' && ch <= '9'); ch, err = self.readChar() {
sb.WriteByte(ch)
}
} else {
err = errors.New("expected integer exponent")
}
}
}
} }
if err != nil && err != io.EOF { if err != nil && err != io.EOF {
tk = self.makeErrorToken(err) tk = self.makeErrorToken(err)
} else { } else {
var value any
err = self.sync(err) err = self.sync(err)
txt := sb.String() txt := sb.String()
if sym == SymFloat { if sym == SymFloat {
value, err = strconv.ParseFloat(txt, 64) value, err = strconv.ParseFloat(txt, 64)
} else if strings.HasPrefix(txt, "0x") {
value, err = strconv.ParseInt(txt, 16, 64)
} else if strings.HasPrefix(txt, "0o") {
value, err = strconv.ParseInt(txt, 8, 64)
} else if strings.HasPrefix(txt, "0b") {
value, err = strconv.ParseInt(txt, 2, 64)
} else { } else {
value, err = strconv.ParseInt(txt, 10, 64) value, err = strconv.ParseInt(txt, numBase, 64)
} }
if err == nil { if err == nil {
tk = self.makeValueToken(sym, txt, value) tk = self.makeValueToken(sym, txt, value)

View File

@ -67,3 +67,17 @@ func (self *Token) Errorf(template string, args ...any) (err error) {
err = fmt.Errorf(fmt.Sprintf("[%d:%d] ", self.row, self.col)+template, args...) err = fmt.Errorf(fmt.Sprintf("[%d:%d] ", self.row, self.col)+template, args...)
return return
} }
func (self *Token) Error() (err error) {
if self.Sym == SymError {
if msg, ok := self.Value.(error); ok {
err = fmt.Errorf("[%d:%d] %v", self.row, self.col, msg)
}
}
return
}
func (self *Token) Errors(msg string) (err error) {
err = fmt.Errorf("[%d:%d] %v", self.row, self.col, msg)
return
}