primitive repl lexing

master
Jordan Orelli 12 years ago
parent 0de1044dda
commit e0c3f2de01

@ -12,6 +12,8 @@
(one two three) (one two three)
"this is a string" "this is a string"
4.0 4.0
((one two) three)
abøne
(dave (dave
1 1
"here's an escaped quote: \" how neat!!!" "here's an escaped quote: \" how neat!!!"
@ -20,3 +22,11 @@
albert-camus albert-camus
3 3
(sam 3 2 2))) (sam 3 2 2)))
(begin (set! x 1)
(set! x (+ x 1))
(* x 2))
(begin (define r 3) (* 3.141592653 (* r r)))

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"io" "io"
"os" "os"
"strings"
) )
type typ3 int type typ3 int
@ -45,17 +46,12 @@ type token struct {
type stateFn func(*lexer) (stateFn, error) type stateFn func(*lexer) (stateFn, error)
type lexer struct { type lexer struct {
input *bufio.Reader io.RuneReader
cur []rune cur []rune
depth int depth int
out chan token out chan token
} }
func (l *lexer) next() (rune, error) {
r, _, err := l.input.ReadRune()
return r, err
}
// clears the current lexem buffer and emits a token of the given type. // clears the current lexem buffer and emits a token of the given type.
// There's no sanity checking to make sure you don't emit some bullshit, so // There's no sanity checking to make sure you don't emit some bullshit, so
// don't fuck it up. // don't fuck it up.
@ -82,7 +78,7 @@ func isDigit(r rune) bool {
// lexes stuff at the root level of the input. // lexes stuff at the root level of the input.
func lexRoot(l *lexer) (stateFn, error) { func lexRoot(l *lexer) (stateFn, error) {
r, err := l.next() r, _, err := l.ReadRune()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -101,7 +97,7 @@ func lexRoot(l *lexer) (stateFn, error) {
func lexOpenParen(l *lexer) (stateFn, error) { func lexOpenParen(l *lexer) (stateFn, error) {
l.out <- token{"(", openParen} l.out <- token{"(", openParen}
l.depth++ l.depth++
r, err := l.next() r, _, err := l.ReadRune()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -109,7 +105,7 @@ func lexOpenParen(l *lexer) (stateFn, error) {
case ' ', '\t', '\n', '\r': case ' ', '\t', '\n', '\r':
return lexWhitespace, nil return lexWhitespace, nil
case '(': case '(':
return nil, fmt.Errorf("the whole (( thing isn't supported yet") return lexOpenParen, nil
case ';': case ';':
return lexComment, nil return lexComment, nil
} }
@ -125,7 +121,7 @@ func lexOpenParen(l *lexer) (stateFn, error) {
// and the lexer shouldn't have a state. I think wehat I'm doing now is // and the lexer shouldn't have a state. I think wehat I'm doing now is
// "wrong" but who honestly gives a shit. // "wrong" but who honestly gives a shit.
func lexWhitespace(l *lexer) (stateFn, error) { func lexWhitespace(l *lexer) (stateFn, error) {
r, err := l.next() r, _, err := l.ReadRune()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -148,7 +144,7 @@ func lexWhitespace(l *lexer) (stateFn, error) {
} }
func lexString(l *lexer) (stateFn, error) { func lexString(l *lexer) (stateFn, error) {
r, err := l.next() r, _, err := l.ReadRune()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -165,7 +161,7 @@ func lexString(l *lexer) (stateFn, error) {
// lex the character *after* the string escape character \ // lex the character *after* the string escape character \
func lexStringEsc(l *lexer) (stateFn, error) { func lexStringEsc(l *lexer) (stateFn, error) {
r, err := l.next() r, _, err := l.ReadRune()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -177,7 +173,7 @@ func lexStringEsc(l *lexer) (stateFn, error) {
// whitespace, close paren, a period to indicate we want a float, or more // whitespace, close paren, a period to indicate we want a float, or more
// digits. Everything else is crap. // digits. Everything else is crap.
func lexInt(l *lexer) (stateFn, error) { func lexInt(l *lexer) (stateFn, error) {
r, err := l.next() r, _, err := l.ReadRune()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -205,7 +201,7 @@ func lexInt(l *lexer) (stateFn, error) {
// once we're in a float, the only valid values are digits, whitespace or close // once we're in a float, the only valid values are digits, whitespace or close
// paren. // paren.
func lexFloat(l *lexer) (stateFn, error) { func lexFloat(l *lexer) (stateFn, error) {
r, err := l.next() r, _, err := l.ReadRune()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -230,7 +226,7 @@ func lexFloat(l *lexer) (stateFn, error) {
// lexes a symbol in progress // lexes a symbol in progress
func lexSymbol(l *lexer) (stateFn, error) { func lexSymbol(l *lexer) (stateFn, error) {
r, err := l.next() r, _, err := l.ReadRune()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -255,7 +251,7 @@ func lexSymbol(l *lexer) (stateFn, error) {
func lexCloseParen(l *lexer) (stateFn, error) { func lexCloseParen(l *lexer) (stateFn, error) {
l.out <- token{")", closeParen} l.out <- token{")", closeParen}
l.depth-- l.depth--
r, err := l.next() r, _, err := l.ReadRune()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -276,7 +272,7 @@ func lexCloseParen(l *lexer) (stateFn, error) {
// lexes a comment // lexes a comment
func lexComment(l *lexer) (stateFn, error) { func lexComment(l *lexer) (stateFn, error) {
r, err := l.next() r, _, err := l.ReadRune()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -291,15 +287,16 @@ func lexComment(l *lexer) (stateFn, error) {
return lexComment, nil return lexComment, nil
} }
func lexs(input string, c chan token) {
lex(strings.NewReader(input), c)
}
// lexes some lispy input from an io.Reader, emiting tokens on chan c. The // lexes some lispy input from an io.Reader, emiting tokens on chan c. The
// channel is closed when the input reaches EOF, signaling that there are no // channel is closed when the input reaches EOF, signaling that there are no
// new tokens. // new tokens.
func lex(input io.Reader, c chan token) { func lex(input io.Reader, c chan token) {
defer close(c) defer close(c)
l := &lexer{ l := &lexer{bufio.NewReader(input), nil, 0, c}
input: bufio.NewReader(input),
out: c,
}
var err error var err error
f := stateFn(lexRoot) f := stateFn(lexRoot)
@ -314,19 +311,42 @@ func lex(input io.Reader, c chan token) {
} }
} }
func main() { func args() {
filename := "input.lisp" filename := os.Args[1]
f, err := os.Open(filename) f, err := os.Open(filename)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "unable to read file ", filename) fmt.Fprintln(os.Stderr, "unable to read file ", filename)
os.Exit(1) os.Exit(1)
} }
c := make(chan token) c := make(chan token)
go lex(f, c) go lex(f, c)
for s := range c { for s := range c {
fmt.Println(s.t, s.lexeme) fmt.Printf("%11s %s\n", s.t, s.lexeme)
}
}
func main() {
if len(os.Args) > 1 {
args()
return
}
printexp := func(c chan token) {
for s := range c {
fmt.Printf("%11s %s\n", s.t, s.lexeme)
}
}
r := bufio.NewReader(os.Stdin)
for {
c := make(chan token)
go printexp(c)
fmt.Print("> ")
line, _, err := r.ReadLine()
if err != nil {
return
}
lexs(string(line), c)
} }
} }

Loading…
Cancel
Save