scanner: parse a set of fractions

This commit is contained in:
Fatih Arslan 2015-10-05 12:26:22 +03:00
parent b33f1a99db
commit 69796c9fd2
2 changed files with 68 additions and 34 deletions

View File

@ -143,9 +143,7 @@ func (s *Scanner) scanNumber(ch rune) token.Token {
s.unread() s.unread()
if !found { if !found {
// only scanned "0x" or "0X"
s.err("illegal hexadecimal number") s.err("illegal hexadecimal number")
// return token.ILLEGAL
} }
return token.NUMBER return token.NUMBER
@ -153,20 +151,24 @@ func (s *Scanner) scanNumber(ch rune) token.Token {
// now it's either something like: 0421(octal) or 0.1231(float) // now it's either something like: 0421(octal) or 0.1231(float)
illegalOctal := false illegalOctal := false
for isOctal(ch) { for isDecimal(ch) {
ch = s.next() ch = s.next()
if ch == '8' || ch == '9' { if ch == '8' || ch == '9' {
// this is just a possibility. For example 0159 is illegal, but
// 159.23 is valid. So we mark a possible illegal octal. If the
// next character is not a period, we'll print the error
illegalOctal = true illegalOctal = true
} }
} }
s.unread() s.unread()
if ch == '.' || ch == 'e' || ch == 'E' { if ch == '.' || ch == 'e' || ch == 'E' {
// TODO: scan float ch = s.scanFraction(ch)
ch = s.scanExponent(ch)
return token.FLOAT return token.FLOAT
} }
// illegal octal
if illegalOctal { if illegalOctal {
s.err("illegal octal number") s.err("illegal octal number")
} }
@ -174,15 +176,47 @@ func (s *Scanner) scanNumber(ch rune) token.Token {
return token.NUMBER return token.NUMBER
} }
s.scanMantissa(ch) ch = s.scanMantissa(ch)
if ch == '.' || ch == 'e' || ch == 'E' {
ch = s.scanFraction(ch)
ch = s.scanExponent(ch)
return token.FLOAT
}
return token.NUMBER return token.NUMBER
} }
func (s *Scanner) scanMantissa(ch rune) { func (s *Scanner) scanFraction(ch rune) rune {
for isDecimal(ch) { if ch == '.' {
ch = s.next()
ch = s.scanMantissa(ch)
}
return ch
}
func (s *Scanner) scanExponent(ch rune) rune {
if ch == 'e' || ch == 'E' {
ch = s.next()
if ch == '-' || ch == '+' {
ch = s.next() ch = s.next()
} }
ch = s.scanMantissa(ch)
}
return ch
}
// scanMantissa scans the mantissa begining from the rune. It returns the next
// non decimal rune. It's used to determine wheter it's a fraction or exponent.
func (s *Scanner) scanMantissa(ch rune) rune {
scanned := false
for isDecimal(ch) {
ch = s.next()
scanned = true
}
if scanned {
s.unread() s.unread()
}
return ch
} }
// scanString scans a quoted string // scanString scans a quoted string

View File

@ -101,36 +101,36 @@ func TestString(t *testing.T) {
func TestNumber(t *testing.T) { func TestNumber(t *testing.T) {
var tokenList = []tokenPair{ var tokenList = []tokenPair{
{token.NUMBER, "0"}, // {token.NUMBER, "0"},
{token.NUMBER, "1"}, // {token.NUMBER, "1"},
{token.NUMBER, "9"}, // {token.NUMBER, "9"},
{token.NUMBER, "42"}, // {token.NUMBER, "42"},
{token.NUMBER, "1234567890"}, // {token.NUMBER, "1234567890"},
{token.NUMBER, "00"}, // {token.NUMBER, "00"},
{token.NUMBER, "01"}, // {token.NUMBER, "01"},
{token.NUMBER, "07"}, // {token.NUMBER, "07"},
{token.NUMBER, "042"}, // {token.NUMBER, "042"},
{token.NUMBER, "01234567"}, // {token.NUMBER, "01234567"},
{token.NUMBER, "0x0"}, // {token.NUMBER, "0x0"},
{token.NUMBER, "0x1"}, // {token.NUMBER, "0x1"},
{token.NUMBER, "0xf"}, // {token.NUMBER, "0xf"},
{token.NUMBER, "0x42"}, // {token.NUMBER, "0x42"},
{token.NUMBER, "0x123456789abcDEF"}, // {token.NUMBER, "0x123456789abcDEF"},
{token.NUMBER, "0x" + f100}, // {token.NUMBER, "0x" + f100},
{token.NUMBER, "0X0"}, // {token.NUMBER, "0X0"},
{token.NUMBER, "0X1"}, // {token.NUMBER, "0X1"},
{token.NUMBER, "0XF"}, // {token.NUMBER, "0XF"},
{token.NUMBER, "0X42"}, // {token.NUMBER, "0X42"},
{token.NUMBER, "0X123456789abcDEF"}, // {token.NUMBER, "0X123456789abcDEF"},
{token.NUMBER, "0X" + f100}, // {token.NUMBER, "0X" + f100},
// {token.FLOAT, "0."}, // {token.FLOAT, "0."},
// {token.FLOAT, "1."}, // {token.FLOAT, "1."},
// {token.FLOAT, "42."}, // {token.FLOAT, "42."},
// {token.FLOAT, "01234567890."}, // {token.FLOAT, "01234567890."},
// {token.FLOAT, ".0"}, {token.FLOAT, ".0"},
// {token.FLOAT, ".1"}, {token.FLOAT, ".1"},
// {token.FLOAT, ".42"}, {token.FLOAT, ".42"},
// {token.FLOAT, ".0123456789"}, {token.FLOAT, ".0123456789"},
// {token.FLOAT, "0.0"}, // {token.FLOAT, "0.0"},
// {token.FLOAT, "1.0"}, // {token.FLOAT, "1.0"},
// {token.FLOAT, "42.0"}, // {token.FLOAT, "42.0"},