diff --git a/golox/internal/runner/scanner.go b/golox/internal/runner/scanner.go index fff253d..646c042 100644 --- a/golox/internal/runner/scanner.go +++ b/golox/internal/runner/scanner.go @@ -108,6 +108,10 @@ func (s *Scanner) scanToken() { s.scanNumber() return } + if isIdentAlpha(c) { + s.scanIdentifier() + return + } lerrors.EmitError(s.line, "Unexpected character.") } } @@ -201,6 +205,18 @@ func (s *Scanner) scanNumber() { ) } +func (s *Scanner) scanIdentifier() { + for isIdentAlphaNumeric(s.peek()) { + s.advance() + } + l := s.source[s.start:s.current] + typ := IDENT + if kTyp, ok := KeywordTypes[l]; ok { + typ = kTyp + } + s.addToken(typ) +} + // addToken produces a single token without a literal value. func (s *Scanner) addToken(typ TokenType) { s.addTokenWithLiteral(typ, nil) diff --git a/golox/internal/runner/scanner_const.go b/golox/internal/runner/scanner_const.go new file mode 100644 index 0000000..aa94484 --- /dev/null +++ b/golox/internal/runner/scanner_const.go @@ -0,0 +1,20 @@ +package runner + +var KeywordTypes = map[string]TokenType{ + "and": AND, + "class": CLASS, + "else": ELSE, + "false": FALSE, + "for": FOR, + "fun": FUN, + "if": IF, + "nil": NIL, + "or": OR, + "print": PRINT, + "return": RETURN, + "super": SUPER, + "this": THIS, + "true": TRUE, + "var": VAR, + "while": WHILE, +} diff --git a/golox/internal/runner/scanner_util.go b/golox/internal/runner/scanner_util.go index a9e6eac..a7b7731 100644 --- a/golox/internal/runner/scanner_util.go +++ b/golox/internal/runner/scanner_util.go @@ -1,5 +1,15 @@ package runner +func isIdentAlphaNumeric(c byte) bool { + return isIdentAlpha(c) || isDigit(c) +} + +func isIdentAlpha(c byte) bool { + return (c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + c == '_' +} + func isDigit(c byte) bool { return c >= '0' && c <= '9' }