From b33f1a99db45f02428bbad09aff3c4b648114d45 Mon Sep 17 00:00:00 2001 From: Fatih Arslan Date: Mon, 5 Oct 2015 11:56:11 +0300 Subject: [PATCH] scanner: implement parsing octals --- scanner/scanner.go | 60 +++++++++++++++++++++++++++-------------- scanner/scanner_test.go | 2 +- token/token.go | 6 ----- 3 files changed, 41 insertions(+), 27 deletions(-) diff --git a/scanner/scanner.go b/scanner/scanner.go index 337691a..8b4e81a 100644 --- a/scanner/scanner.go +++ b/scanner/scanner.go @@ -111,7 +111,6 @@ func (s *Scanner) Scan() (tok token.Token) { if lit == "true" || lit == "false" { tok = token.BOOL } - case isDecimal(ch): tok = s.scanNumber(ch) default: @@ -131,14 +130,48 @@ func (s *Scanner) Scan() (tok token.Token) { // scanNumber scans a HCL number definition starting with the given rune func (s *Scanner) scanNumber(ch rune) token.Token { if ch == '0' { - // check hexadecimal or float + // check for hexadecimal, octal or float ch = s.next() if ch == 'x' || ch == 'X' { + // hexadecimal ch = s.next() - s.scanHexadecimal(ch) + found := false + for isHexadecimal(ch) { + ch = s.next() + found = true + } + s.unread() + + if !found { + // only scanned "0x" or "0X" + s.err("illegal hexadecimal number") + // return token.ILLEGAL + } + return token.NUMBER } + // now it's either something like: 0421(octal) or 0.1231(float) + illegalOctal := false + for isOctal(ch) { + ch = s.next() + if ch == '8' || ch == '9' { + illegalOctal = true + } + } + s.unread() + + if ch == '.' || ch == 'e' || ch == 'E' { + // TODO: scan float + return token.FLOAT + } + + // illegal octal + if illegalOctal { + s.err("illegal octal number") + } + + return token.NUMBER } s.scanMantissa(ch) @@ -152,23 +185,6 @@ func (s *Scanner) scanMantissa(ch rune) { s.unread() } -func (s *Scanner) scanHexadecimal(ch rune) { - found := false - - // after "0x" or "0X" - for isHexadecimal(ch) { - ch = s.next() - found = true - } - - if !found { - // only scanned "0x" or "0X" - s.err("illegal hexadecimal number") - } - - s.unread() -} - // scanString scans a quoted string func (s *Scanner) scanString() { for { @@ -286,6 +302,10 @@ func isDigit(ch rune) bool { return '0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch) } +func isOctal(ch rune) bool { + return '0' <= ch && ch <= '7' +} + func isDecimal(ch rune) bool { return '0' <= ch && ch <= '9' } diff --git a/scanner/scanner_test.go b/scanner/scanner_test.go index 4df11ea..c7e2837 100644 --- a/scanner/scanner_test.go +++ b/scanner/scanner_test.go @@ -19,7 +19,7 @@ func testTokenList(t *testing.T, tokenList []tokenPair) { // create artifical source code buf := new(bytes.Buffer) for _, ident := range tokenList { - fmt.Fprintf(buf, " \t%s\n", ident.text) + fmt.Fprintf(buf, "%s\n", ident.text) } s, err := NewScanner(buf) diff --git a/token/token.go b/token/token.go index cbd822d..9ebb696 100644 --- a/token/token.go +++ b/token/token.go @@ -31,9 +31,6 @@ const ( ASSIGN // = ADD // + SUB // - - - EPLUS // e - EMINUS // e- operator_end ) @@ -60,9 +57,6 @@ var tokens = [...]string{ ASSIGN: "=", ADD: "+", SUB: "-", - - EPLUS: "e", - EMINUS: "e-", } // String returns the string corresponding to the token tok.