001
This commit is contained in:
commit
231e86bfbf
5 changed files with 107 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
.idea
|
3
go.mod
Normal file
3
go.mod
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
module lexer-and-parser-thing
|
||||||
|
|
||||||
|
go 1.24.0
|
16
main.go
Normal file
16
main.go
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
const fynCode = `12 + 34 * 56 / 78 - 90`
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
scanner := Scanner{source: fynCode}
|
||||||
|
|
||||||
|
token := scanner.Consume()
|
||||||
|
for token.kind != "eof" {
|
||||||
|
fmt.Println(token)
|
||||||
|
|
||||||
|
token = scanner.Consume()
|
||||||
|
}
|
||||||
|
}
|
74
scanner.go
Normal file
74
scanner.go
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
type Scanner struct {
|
||||||
|
source string
|
||||||
|
cursor int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Scanner) Consume() Token {
|
||||||
|
if s.cursor >= len(s.source) {
|
||||||
|
return Token{kind: "eof", lexeme: "EOF"}
|
||||||
|
}
|
||||||
|
|
||||||
|
s.readWhile(isWhitespace)
|
||||||
|
|
||||||
|
next := s.peek()
|
||||||
|
|
||||||
|
if isDigit(next) {
|
||||||
|
lexeme := s.readWhile(isDigit)
|
||||||
|
|
||||||
|
return Token{kind: "number", lexeme: lexeme}
|
||||||
|
}
|
||||||
|
|
||||||
|
kind, ok := kinds[next]
|
||||||
|
if ok {
|
||||||
|
lexeme := s.read()
|
||||||
|
|
||||||
|
return Token{kind: kind, lexeme: string(lexeme)}
|
||||||
|
}
|
||||||
|
|
||||||
|
lexeme := s.readWhile(notWhitespace)
|
||||||
|
|
||||||
|
return Token{kind: "unknown", lexeme: lexeme}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Scanner) peek() rune {
|
||||||
|
if s.cursor >= len(s.source) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return rune(s.source[s.cursor])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Scanner) read() rune {
|
||||||
|
c := rune(s.source[s.cursor])
|
||||||
|
|
||||||
|
s.cursor += 1
|
||||||
|
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Scanner) readWhile(predicate func(rune) bool) string {
|
||||||
|
lexeme := ""
|
||||||
|
|
||||||
|
c := s.peek()
|
||||||
|
for s.cursor < len(s.source) && predicate(c) {
|
||||||
|
lexeme += string(s.read())
|
||||||
|
|
||||||
|
c = s.peek()
|
||||||
|
}
|
||||||
|
|
||||||
|
return lexeme
|
||||||
|
}
|
||||||
|
|
||||||
|
func isWhitespace(c rune) bool {
|
||||||
|
return c == ' ' || c == '\t' || c == '\n'
|
||||||
|
}
|
||||||
|
|
||||||
|
func notWhitespace(c rune) bool {
|
||||||
|
return !isWhitespace(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDigit(c rune) bool {
|
||||||
|
return '0' <= c && c <= '9'
|
||||||
|
}
|
13
token.go
Normal file
13
token.go
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
var kinds = map[rune]string{
|
||||||
|
'+': "plus",
|
||||||
|
'-': "minus",
|
||||||
|
'*': "asterisk",
|
||||||
|
'/': "slash",
|
||||||
|
}
|
||||||
|
|
||||||
|
type Token struct {
|
||||||
|
kind string
|
||||||
|
lexeme string
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue