Adds lexer and beginnings of parser
parent
4fc28a42bd
commit
dbe94ee680
@ -0,0 +1,157 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Token struct {
|
||||
kind int
|
||||
val string
|
||||
}
|
||||
|
||||
type scanner struct {
|
||||
r *bufio.Reader
|
||||
}
|
||||
|
||||
var eof rune = rune(0)
|
||||
|
||||
const (
|
||||
Number int = iota
|
||||
Text
|
||||
Opperator
|
||||
Whitespace
|
||||
Comment
|
||||
Newline
|
||||
End
|
||||
|
||||
Illegal
|
||||
)
|
||||
|
||||
// - ~ + - ~ + //
|
||||
// Receivers //
|
||||
// - ~ + - ~ + //
|
||||
|
||||
func (s *scanner) read() rune {
|
||||
ch, _, err := s.r.ReadRune()
|
||||
if err != nil {
|
||||
return eof
|
||||
}
|
||||
return ch
|
||||
}
|
||||
|
||||
|
||||
func (s *scanner) unread() {
|
||||
_ = s.r.UnreadRune()
|
||||
}
|
||||
|
||||
|
||||
func (s *scanner) scan() Token {
|
||||
char := s.read()
|
||||
|
||||
if isWhitespace(char) {
|
||||
s.unread()
|
||||
return s.scanWhitespace()
|
||||
} else if isLetter(char) {
|
||||
s.unread()
|
||||
return s.scanText()
|
||||
} else if isNumber(char) {
|
||||
s.unread()
|
||||
return s.scanNumber()
|
||||
} else if char == '#' {
|
||||
s.unread()
|
||||
return s.scanComment()
|
||||
} else if isOpperator() {
|
||||
return Token{Opperator, string(char)}
|
||||
} else if char == '\n' {
|
||||
return Token{Newline,""}
|
||||
} else if char == eof {
|
||||
return Token{End, ""}
|
||||
}
|
||||
|
||||
return Token{illegal, string(char)}
|
||||
}
|
||||
|
||||
|
||||
func (s *scanner) scanWhitespace() Token {
|
||||
var buf bytes.Buffer
|
||||
buf.WriteRune(s.read())
|
||||
|
||||
for {
|
||||
if ch := s.read(); ch == eof {
|
||||
s.unread()
|
||||
break
|
||||
} else if !isWhitespace(ch) {
|
||||
s.unread()
|
||||
break
|
||||
} else {
|
||||
_, _ = buf.WriteRune(ch)
|
||||
}
|
||||
}
|
||||
|
||||
return Token{Whitespace, buf.String()}
|
||||
}
|
||||
|
||||
|
||||
func (s *scanner) scanText() Token {
|
||||
var buf bytes.Buffer
|
||||
buf.WriteRune(s.read())
|
||||
|
||||
for {
|
||||
if ch := s.read(); ch == eof {
|
||||
s.unread()
|
||||
break
|
||||
} else if !isLetter(ch) {
|
||||
s.unread()
|
||||
break
|
||||
} else {
|
||||
_, _ = buf.WriteRune(ch)
|
||||
}
|
||||
|
||||
return Token{Text, buf.String()}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func (s *scanner) scanComment() {
|
||||
var buf bytes.Buffer
|
||||
buf.WriteRune(s.read())
|
||||
|
||||
for {
|
||||
if ch := s.read(); ch == eof || ch == '\n' {
|
||||
s.unread()
|
||||
break
|
||||
} else {
|
||||
_, _ = buf.WriteRune(ch)
|
||||
}
|
||||
}
|
||||
|
||||
return Token{Comment, buf.String()}
|
||||
}
|
||||
|
||||
|
||||
// - ~ + - ~ + //
|
||||
// Functions //
|
||||
// - ~ + - ~ + //
|
||||
|
||||
func isWhitespace(ch rune) bool {
|
||||
return ch == ' ' || ch == '\t' || ch == '\r'
|
||||
}
|
||||
|
||||
func isLetter(ch rune) bool {
|
||||
return ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z'
|
||||
}
|
||||
|
||||
func isNumber(ch rune) bool {
|
||||
return ch >= '0' && ch <= '9'
|
||||
}
|
||||
|
||||
func isOpperator(ch rune) bool {
|
||||
return ch == '=' || ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '^' || ch == '%'
|
||||
}
|
||||
|
||||
func NewScanner(r io.Reader) *scanner {
|
||||
return &scanner{r: bufio.NewReader(r)}
|
||||
}
|
Loading…
Reference in New Issue