mirror of
https://github.com/Fluffy-Bean/GoLox.git
synced 2025-05-14 07:42:15 +00:00
157 lines
2.3 KiB
Go
157 lines
2.3 KiB
Go
package main
|
|
|
|
type Scanner struct {
|
|
source string
|
|
tokens []Token
|
|
start int
|
|
current int
|
|
line int
|
|
}
|
|
|
|
func (s *Scanner) ScanTokens() []Token {
|
|
for !s.isAtEnd() {
|
|
s.start = s.current
|
|
s.scanToken()
|
|
}
|
|
|
|
s.tokens = append(s.tokens, Token{
|
|
Type: EOF,
|
|
Lexeme: "",
|
|
Literal: "",
|
|
Line: s.line,
|
|
})
|
|
return s.tokens
|
|
}
|
|
|
|
func (s *Scanner) scanToken() {
|
|
c := s.advance()
|
|
switch c {
|
|
case "(":
|
|
s.addToken(LeftBrace)
|
|
break
|
|
case ")":
|
|
s.addToken(RightBrace)
|
|
break
|
|
case "{":
|
|
s.addToken(LeftBrace)
|
|
break
|
|
case "}":
|
|
s.addToken(RightBrace)
|
|
break
|
|
case ",":
|
|
s.addToken(Comma)
|
|
break
|
|
case ".":
|
|
s.addToken(Dot)
|
|
break
|
|
case "-":
|
|
s.addToken(Minus)
|
|
break
|
|
case "+":
|
|
s.addToken(Plus)
|
|
break
|
|
case ";":
|
|
s.addToken(Semicolon)
|
|
break
|
|
case "*":
|
|
s.addToken(Star)
|
|
break
|
|
case "!":
|
|
if s.match("=") {
|
|
s.addToken(BangEqual)
|
|
} else {
|
|
s.addToken(Bang)
|
|
}
|
|
break
|
|
case "=":
|
|
if s.match("=") {
|
|
s.addToken(EqualEqual)
|
|
} else {
|
|
s.addToken(Equal)
|
|
}
|
|
break
|
|
case "<":
|
|
if s.match("=") {
|
|
s.addToken(LessEqual)
|
|
} else {
|
|
s.addToken(Less)
|
|
}
|
|
break
|
|
case ">":
|
|
if s.match("=") {
|
|
s.addToken(GreaterEqual)
|
|
} else {
|
|
s.addToken(Greater)
|
|
}
|
|
break
|
|
case "/":
|
|
if s.match("/") {
|
|
for s.peek() != "\n" && !s.isAtEnd() {
|
|
s.advance()
|
|
}
|
|
} else {
|
|
s.addToken(Slash)
|
|
}
|
|
break
|
|
case " ":
|
|
case "\t":
|
|
case "\r":
|
|
// ignore whitespace
|
|
break
|
|
case "\n":
|
|
s.line += 1
|
|
break
|
|
default:
|
|
fuck(s.line, "Unexpected Char.")
|
|
break
|
|
}
|
|
}
|
|
|
|
func (s *Scanner) advance() string {
|
|
c := string(s.source[s.current])
|
|
s.current += 1
|
|
return c
|
|
}
|
|
|
|
func (s *Scanner) peek() string {
|
|
if s.isAtEnd() {
|
|
return ""
|
|
}
|
|
return string(s.source[s.current])
|
|
}
|
|
|
|
func (s *Scanner) match(expected string) bool {
|
|
if s.isAtEnd() {
|
|
return false
|
|
}
|
|
if string(s.source[s.current]) != expected {
|
|
return false
|
|
}
|
|
s.current += 1
|
|
return true
|
|
}
|
|
|
|
func (s *Scanner) addToken(token int) {
|
|
s.tokens = append(s.tokens, Token{
|
|
Type: token,
|
|
Lexeme: s.source[s.start:s.current],
|
|
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) isAtEnd() bool {
|
|
return s.current >= len(s.source)
|
|
}
|
|
|
|
func NewScanner(source string) *Scanner {
|
|
return &Scanner{
|
|
source: source,
|
|
tokens: []Token{},
|
|
start: 0,
|
|
current: 0,
|
|
line: 0,
|
|
}
|
|
}
|