diff --git a/scanner.go b/scanner.go index e4bda65..cf5f263 100644 --- a/scanner.go +++ b/scanner.go @@ -1,5 +1,10 @@ package main +import ( + "fmt" + "strconv" +) + type Scanner struct { source string tokens []Token @@ -92,6 +97,23 @@ func (s *Scanner) scanToken() { } else { s.addToken(Slash) } + break + case "\"": + for s.peek() != "\"" && !s.isAtEnd() { + if s.peek() == "\n" { + s.line += 1 + } + s.advance() + } + + if s.isAtEnd() { + fuck(s.line, "Undetermined string") + return + } + + s.advance() // close " + s.addTokenWithLiteral(String, s.source[s.start+1:s.current-1]) // +- to remove "" + break case " ": case "\t": @@ -102,7 +124,28 @@ func (s *Scanner) scanToken() { s.line += 1 break default: - fuck(s.line, "Unexpected Char.") + if s.isDigit(c) { + for s.isDigit(s.peek()) { + s.advance() + } + + if s.peek() == "." && s.isDigit(s.peekAfter()) { + s.advance() // eated . + + for s.isDigit(s.peek()) { + s.advance() + } + } + + number, err := strconv.ParseFloat(s.source[s.start:s.current], 64) + if err != nil { + fuck(s.line, "Undetermined int") + } + + s.addTokenWithLiteral(Number, fmt.Sprintf("%f", number)) // convert back to string, lol + } else { + fuck(s.line, "Unexpected Character") + } break } } @@ -120,6 +163,13 @@ func (s *Scanner) peek() string { return string(s.source[s.current]) } +func (s *Scanner) peekAfter() string { + if s.current+1 >= len(s.source) { + return "" + } + return string(s.source[s.current+1]) +} + func (s *Scanner) match(expected string) bool { if s.isAtEnd() { return false @@ -131,6 +181,16 @@ func (s *Scanner) match(expected string) bool { return true } +func (s *Scanner) isDigit(val string) bool { + // Lazy way of doing thia, Atoi could work, but unsure if it has any funkiness to it..... + for _, number := range "0123456789" { + if val == string(number) { + return true + } + } + return false +} + func (s *Scanner) addToken(token int) { s.tokens = append(s.tokens, Token{ Type: token, @@ -142,6 +202,15 @@ func (s *Scanner) addToken(token int) { //fmt.Println(s.tokens[len(s.tokens)-1]) } +func (s *Scanner) addTokenWithLiteral(token int, value string) { + s.tokens = append(s.tokens, Token{ + Type: token, + Lexeme: s.source[s.start:s.current], + Literal: value, + Line: s.line, + }) +} + func (s *Scanner) isAtEnd() bool { return s.current >= len(s.source) } diff --git a/scripts/example.lox b/scripts/example.lox index fee65cb..0b69b32 100644 --- a/scripts/example.lox +++ b/scripts/example.lox @@ -1,3 +1,5 @@ // this is a comment (( )){} // grouping stuff !*+-/ =<> <= == // operators +"aurgh" +69.621 diff --git a/tokens.go b/tokens.go index a22268b..c03415f 100644 --- a/tokens.go +++ b/tokens.go @@ -57,10 +57,10 @@ const ( type Token struct { Type int Lexeme string - Literal string + Literal string // JS moment Line int } func (t Token) String() string { - return fmt.Sprintf("%d %s %s", t.Type, t.Lexeme, t.Literal) + return fmt.Sprintf("[%d] %d %s %s", t.Line, t.Type, t.Lexeme, t.Literal) }