From a63c07d5bf966a65778e9ebdef14d44a2e9dc828 Mon Sep 17 00:00:00 2001 From: Fluffy Date: Mon, 23 Sep 2024 12:34:17 +0100 Subject: [PATCH] Find keywords Use runes/chars for characters --- scanner.go | 122 +++++++++++++++------------- scripts/function.lox | 12 +++ scripts/{example.lox => tokens.lox} | 0 tokens.go | 21 ++++- 4 files changed, 98 insertions(+), 57 deletions(-) create mode 100644 scripts/function.lox rename scripts/{example.lox => tokens.lox} (100%) diff --git a/scanner.go b/scanner.go index cf5f263..2d45c1c 100644 --- a/scanner.go +++ b/scanner.go @@ -31,76 +31,76 @@ func (s *Scanner) ScanTokens() []Token { func (s *Scanner) scanToken() { c := s.advance() switch c { - case "(": + case '(': s.addToken(LeftBrace) break - case ")": + case ')': s.addToken(RightBrace) break - case "{": + case '{': s.addToken(LeftBrace) break - case "}": + case '}': s.addToken(RightBrace) break - case ",": + case ',': s.addToken(Comma) break - case ".": + case '.': s.addToken(Dot) break - case "-": + case '-': s.addToken(Minus) break - case "+": + case '+': s.addToken(Plus) break - case ";": + case ';': s.addToken(Semicolon) break - case "*": + case '*': s.addToken(Star) break - case "!": - if s.match("=") { + case '!': + if s.match('=') { s.addToken(BangEqual) } else { s.addToken(Bang) } break - case "=": - if s.match("=") { + case '=': + if s.match('=') { s.addToken(EqualEqual) } else { s.addToken(Equal) } break - case "<": - if s.match("=") { + case '<': + if s.match('=') { s.addToken(LessEqual) } else { s.addToken(Less) } break - case ">": - if s.match("=") { + case '>': + if s.match('=') { s.addToken(GreaterEqual) } else { s.addToken(Greater) } break - case "/": - if s.match("/") { - for s.peek() != "\n" && !s.isAtEnd() { + case '/': + if s.match('/') { + for s.peek() != '\n' && !s.isAtEnd() { s.advance() } } else { s.addToken(Slash) } break - case "\"": - for s.peek() != "\"" && !s.isAtEnd() { - if s.peek() == "\n" { + case '"': + for s.peek() != '"' && !s.isAtEnd() { + if s.peek() == '\n' { s.line += 1 } s.advance() @@ -115,12 +115,11 @@ func (s *Scanner) scanToken() { s.addTokenWithLiteral(String, s.source[s.start+1:s.current-1]) // +- to remove "" break - case " ": - case "\t": - case "\r": - // ignore whitespace + case ' ': + case '\t': + case '\r': break - case "\n": + case '\n': s.line += 1 break default: @@ -128,10 +127,8 @@ func (s *Scanner) scanToken() { for s.isDigit(s.peek()) { s.advance() } - - if s.peek() == "." && s.isDigit(s.peekAfter()) { + if s.peek() == '.' && s.isDigit(s.peekAfter()) { s.advance() // eated . - for s.isDigit(s.peek()) { s.advance() } @@ -143,6 +140,19 @@ func (s *Scanner) scanToken() { } s.addTokenWithLiteral(Number, fmt.Sprintf("%f", number)) // convert back to string, lol + } else if s.isAlpha(c) { + for s.isAlpha(s.peek()) { + s.advance() + } + + keyword := s.source[s.start:s.current] + + val, ok := Tokens[keyword] + if !ok { + val = Identifier + } + + s.addToken(val) } else { fuck(s.line, "Unexpected Character") } @@ -150,45 +160,51 @@ func (s *Scanner) scanToken() { } } -func (s *Scanner) advance() string { - c := string(s.source[s.current]) +func (s *Scanner) advance() rune { + c := rune(s.source[s.current]) s.current += 1 return c } -func (s *Scanner) peek() string { +func (s *Scanner) peek() rune { if s.isAtEnd() { - return "" + return '0' } - return string(s.source[s.current]) + return rune(s.source[s.current]) } -func (s *Scanner) peekAfter() string { +func (s *Scanner) peekAfter() rune { if s.current+1 >= len(s.source) { - return "" + return '0' } - return string(s.source[s.current+1]) + return rune(s.source[s.current+1]) } -func (s *Scanner) match(expected string) bool { +func (s *Scanner) match(c rune) bool { if s.isAtEnd() { return false } - if string(s.source[s.current]) != expected { + if rune(s.source[s.current]) != c { return false } s.current += 1 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) isDigit(c rune) bool { + return c >= '0' && c <= '9' +} + +func (s *Scanner) isAlpha(c rune) bool { + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' +} + +func (s *Scanner) isAlphaNumeric(c rune) bool { + return s.isAlpha(c) || s.isDigit(c) +} + +func (s *Scanner) isAtEnd() bool { + return s.current >= len(s.source) } func (s *Scanner) addToken(token int) { @@ -198,8 +214,6 @@ func (s *Scanner) addToken(token int) { Literal: "", Line: s.line, }) - //fmt.Printf("[%d %d %d] ", s.line, s.current, s.start) - //fmt.Println(s.tokens[len(s.tokens)-1]) } func (s *Scanner) addTokenWithLiteral(token int, value string) { @@ -211,10 +225,6 @@ func (s *Scanner) addTokenWithLiteral(token int, value string) { }) } -func (s *Scanner) isAtEnd() bool { - return s.current >= len(s.source) -} - func NewScanner(source string) *Scanner { return &Scanner{ source: source, diff --git a/scripts/function.lox b/scripts/function.lox new file mode 100644 index 0000000..0009630 --- /dev/null +++ b/scripts/function.lox @@ -0,0 +1,12 @@ +fun main() { + example("world") +} + +fun example(name) { + print "Hello, " + print name + print "!\n" +} + +// Start program +main() diff --git a/scripts/example.lox b/scripts/tokens.lox similarity index 100% rename from scripts/example.lox rename to scripts/tokens.lox diff --git a/tokens.go b/tokens.go index c03415f..763464f 100644 --- a/tokens.go +++ b/tokens.go @@ -41,7 +41,7 @@ const ( Fun For If - Nah + Null Or Print Return @@ -54,6 +54,25 @@ const ( EOF ) +var Tokens = map[string]int{ + "and": And, + "class": Class, + "else": Else, + "false": False, + "fun": Fun, + "for": For, + "if": If, + "null": Null, + "or": Or, + "print": Print, + "return": Return, + "super": Super, + "this": This, + "true": True, + "var": Var, + "while": While, +} + type Token struct { Type int Lexeme string