Find keywords

Use runes/chars for characters
This commit is contained in:
Michał 2024-09-23 12:34:17 +01:00
parent 175d300e03
commit a63c07d5bf
4 changed files with 98 additions and 57 deletions

View file

@ -31,76 +31,76 @@ func (s *Scanner) ScanTokens() []Token {
func (s *Scanner) scanToken() { func (s *Scanner) scanToken() {
c := s.advance() c := s.advance()
switch c { switch c {
case "(": case '(':
s.addToken(LeftBrace) s.addToken(LeftBrace)
break break
case ")": case ')':
s.addToken(RightBrace) s.addToken(RightBrace)
break break
case "{": case '{':
s.addToken(LeftBrace) s.addToken(LeftBrace)
break break
case "}": case '}':
s.addToken(RightBrace) s.addToken(RightBrace)
break break
case ",": case ',':
s.addToken(Comma) s.addToken(Comma)
break break
case ".": case '.':
s.addToken(Dot) s.addToken(Dot)
break break
case "-": case '-':
s.addToken(Minus) s.addToken(Minus)
break break
case "+": case '+':
s.addToken(Plus) s.addToken(Plus)
break break
case ";": case ';':
s.addToken(Semicolon) s.addToken(Semicolon)
break break
case "*": case '*':
s.addToken(Star) s.addToken(Star)
break break
case "!": case '!':
if s.match("=") { if s.match('=') {
s.addToken(BangEqual) s.addToken(BangEqual)
} else { } else {
s.addToken(Bang) s.addToken(Bang)
} }
break break
case "=": case '=':
if s.match("=") { if s.match('=') {
s.addToken(EqualEqual) s.addToken(EqualEqual)
} else { } else {
s.addToken(Equal) s.addToken(Equal)
} }
break break
case "<": case '<':
if s.match("=") { if s.match('=') {
s.addToken(LessEqual) s.addToken(LessEqual)
} else { } else {
s.addToken(Less) s.addToken(Less)
} }
break break
case ">": case '>':
if s.match("=") { if s.match('=') {
s.addToken(GreaterEqual) s.addToken(GreaterEqual)
} else { } else {
s.addToken(Greater) s.addToken(Greater)
} }
break break
case "/": case '/':
if s.match("/") { if s.match('/') {
for s.peek() != "\n" && !s.isAtEnd() { for s.peek() != '\n' && !s.isAtEnd() {
s.advance() s.advance()
} }
} else { } else {
s.addToken(Slash) s.addToken(Slash)
} }
break break
case "\"": case '"':
for s.peek() != "\"" && !s.isAtEnd() { for s.peek() != '"' && !s.isAtEnd() {
if s.peek() == "\n" { if s.peek() == '\n' {
s.line += 1 s.line += 1
} }
s.advance() s.advance()
@ -115,12 +115,11 @@ func (s *Scanner) scanToken() {
s.addTokenWithLiteral(String, s.source[s.start+1:s.current-1]) // +- to remove "" s.addTokenWithLiteral(String, s.source[s.start+1:s.current-1]) // +- to remove ""
break break
case " ": case ' ':
case "\t": case '\t':
case "\r": case '\r':
// ignore whitespace
break break
case "\n": case '\n':
s.line += 1 s.line += 1
break break
default: default:
@ -128,10 +127,8 @@ func (s *Scanner) scanToken() {
for s.isDigit(s.peek()) { for s.isDigit(s.peek()) {
s.advance() s.advance()
} }
if s.peek() == '.' && s.isDigit(s.peekAfter()) {
if s.peek() == "." && s.isDigit(s.peekAfter()) {
s.advance() // eated . s.advance() // eated .
for s.isDigit(s.peek()) { for s.isDigit(s.peek()) {
s.advance() s.advance()
} }
@ -143,6 +140,19 @@ func (s *Scanner) scanToken() {
} }
s.addTokenWithLiteral(Number, fmt.Sprintf("%f", number)) // convert back to string, lol 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 { } else {
fuck(s.line, "Unexpected Character") fuck(s.line, "Unexpected Character")
} }
@ -150,45 +160,51 @@ func (s *Scanner) scanToken() {
} }
} }
func (s *Scanner) advance() string { func (s *Scanner) advance() rune {
c := string(s.source[s.current]) c := rune(s.source[s.current])
s.current += 1 s.current += 1
return c return c
} }
func (s *Scanner) peek() string { func (s *Scanner) peek() rune {
if s.isAtEnd() { 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) { 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() { if s.isAtEnd() {
return false return false
} }
if string(s.source[s.current]) != expected { if rune(s.source[s.current]) != c {
return false return false
} }
s.current += 1 s.current += 1
return true return true
} }
func (s *Scanner) isDigit(val string) bool { func (s *Scanner) isDigit(c rune) bool {
// Lazy way of doing thia, Atoi could work, but unsure if it has any funkiness to it..... return c >= '0' && c <= '9'
for _, number := range "0123456789" { }
if val == string(number) {
return true func (s *Scanner) isAlpha(c rune) bool {
} return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'
} }
return false
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) { func (s *Scanner) addToken(token int) {
@ -198,8 +214,6 @@ func (s *Scanner) addToken(token int) {
Literal: "", Literal: "",
Line: s.line, 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) { 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 { func NewScanner(source string) *Scanner {
return &Scanner{ return &Scanner{
source: source, source: source,

12
scripts/function.lox Normal file
View file

@ -0,0 +1,12 @@
fun main() {
example("world")
}
fun example(name) {
print "Hello, "
print name
print "!\n"
}
// Start program
main()

View file

@ -41,7 +41,7 @@ const (
Fun Fun
For For
If If
Nah Null
Or Or
Print Print
Return Return
@ -54,6 +54,25 @@ const (
EOF 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 Token struct {
Type int Type int
Lexeme string Lexeme string