master
Jordan Orelli 12 years ago
parent 7bf30556ad
commit a3791fcc0e

@ -10,27 +10,27 @@ type typ3 int
const ( const (
invalid typ3 = iota invalid typ3 = iota
int3ger integerToken
symbol symbolToken
openParen openParenToken
closeParen closeParenToken
str1ng stringToken
fl0at floatToken
) )
func (t typ3) String() string { func (t typ3) String() string {
switch t { switch t {
case int3ger: case integerToken:
return "integer" return "integer"
case symbol: case symbolToken:
return "symbol" return "symbol"
case openParen: case openParenToken:
return "open_paren" return "open_paren"
case closeParen: case closeParenToken:
return "close_paren" return "close_paren"
case str1ng: case stringToken:
return "string" return "string"
case fl0at: case floatToken:
return "float" return "float"
} }
panic("wtf") panic("wtf")
@ -85,7 +85,7 @@ func debugPrint(s string) {
// lexes an open parenthesis // lexes an open parenthesis
func lexOpenParen(l *lexer) (stateFn, error) { func lexOpenParen(l *lexer) (stateFn, error) {
debugPrint("-->lexOpenParen") debugPrint("-->lexOpenParen")
l.out <- token{"(", openParen} l.out <- token{"(", openParenToken}
l.depth++ l.depth++
r, _, err := l.ReadRune() r, _, err := l.ReadRune()
if err != nil { if err != nil {
@ -146,7 +146,7 @@ func lexString(l *lexer) (stateFn, error) {
} }
switch r { switch r {
case '"': case '"':
l.emit(str1ng) l.emit(stringToken)
return lexWhitespace, nil return lexWhitespace, nil
case '\\': case '\\':
return lexStringEsc, nil return lexStringEsc, nil
@ -177,16 +177,16 @@ func lexInt(l *lexer) (stateFn, error) {
} }
switch r { switch r {
case ' ', '\t', '\n', '\r': case ' ', '\t', '\n', '\r':
l.emit(int3ger) l.emit(integerToken)
return lexWhitespace, nil return lexWhitespace, nil
case '.': case '.':
l.append(r) l.append(r)
return lexFloat, nil return lexFloat, nil
case ')': case ')':
l.emit(int3ger) l.emit(integerToken)
return lexCloseParen, nil return lexCloseParen, nil
case ';': case ';':
l.emit(int3ger) l.emit(integerToken)
return lexComment, nil return lexComment, nil
} }
if isDigit(r) { if isDigit(r) {
@ -207,13 +207,13 @@ func lexFloat(l *lexer) (stateFn, error) {
switch r { switch r {
case ' ', '\t', '\n', '\r': case ' ', '\t', '\n', '\r':
l.emit(fl0at) l.emit(floatToken)
return lexWhitespace, nil return lexWhitespace, nil
case ')': case ')':
l.emit(fl0at) l.emit(floatToken)
return lexCloseParen, nil return lexCloseParen, nil
case ';': case ';':
l.emit(fl0at) l.emit(floatToken)
return lexComment, nil return lexComment, nil
} }
if isDigit(r) { if isDigit(r) {
@ -234,13 +234,13 @@ func lexSymbol(l *lexer) (stateFn, error) {
switch r { switch r {
case ' ', '\t', '\n', '\r': case ' ', '\t', '\n', '\r':
debugPrint("ending lexSymbol on whitespace") debugPrint("ending lexSymbol on whitespace")
l.emit(symbol) l.emit(symbolToken)
return lexWhitespace, nil return lexWhitespace, nil
case ')': case ')':
l.emit(symbol) l.emit(symbolToken)
return lexCloseParen, nil return lexCloseParen, nil
case ';': case ';':
l.emit(symbol) l.emit(symbolToken)
return lexComment, nil return lexComment, nil
default: default:
l.append(r) l.append(r)
@ -252,7 +252,7 @@ func lexSymbol(l *lexer) (stateFn, error) {
// lex a close parenthesis // lex a close parenthesis
func lexCloseParen(l *lexer) (stateFn, error) { func lexCloseParen(l *lexer) (stateFn, error) {
debugPrint("-->lexCloseParen") debugPrint("-->lexCloseParen")
l.out <- token{")", closeParen} l.out <- token{")", closeParenToken}
l.depth-- l.depth--
r, _, err := l.ReadRune() r, _, err := l.ReadRune()
if err != nil { if err != nil {

@ -2,13 +2,92 @@ package main
import ( import (
"bufio" "bufio"
"errors"
"fmt" "fmt"
"io" "io"
"os" "os"
"strconv"
) )
var DEBUG = false var DEBUG = false
type sexp []interface{}
type symbol string
// parses the string lexeme into a value that can be eval'd
func atom(t token) (interface{}, error) {
switch t.t {
case integerToken:
val, err := strconv.ParseInt(t.lexeme, 10, 64)
if err != nil {
return nil, err
}
return val, nil
case floatToken:
val, err := strconv.ParseFloat(t.lexeme, 64)
if err != nil {
return nil, err
}
return val, nil
case stringToken:
return t.lexeme, nil
case symbolToken:
return symbol(t.lexeme), nil
}
return nil, fmt.Errorf("unable to atomize token: %v", t)
}
// reads in tokens on the channel until a matching close paren is found.
func (s *sexp) readIn(c chan token) error {
for t := range c {
switch t.t {
case closeParenToken:
return nil
case openParenToken:
child := make(sexp, 0)
if err := child.readIn(c); err != nil {
return err
}
*s = append(*s, child)
default:
v, err := atom(t)
if err != nil {
return err
}
*s = append(*s, v)
}
}
return errors.New("unexpected EOF in sexp.readIn")
}
// parses one value that can be evaled from the channel
func parse(c chan token) (interface{}, error) {
for t := range c {
switch t.t {
case closeParenToken:
return nil, errors.New("unexpected EOF in read")
case openParenToken:
s := make(sexp, 0)
if err := s.readIn(c); err != nil {
return nil, err
}
return s, nil
default:
return atom(t)
}
}
return nil, io.EOF
}
func eval(v interface{}) {
fmt.Println(v)
}
func args() { func args() {
filename := os.Args[1] filename := os.Args[1]
f, err := os.Open(filename) f, err := os.Open(filename)
@ -21,9 +100,17 @@ func args() {
c := make(chan token, 32) c := make(chan token, 32)
go lex(bufio.NewReader(f), c) go lex(bufio.NewReader(f), c)
for s := range c { for {
fmt.Printf("%11s %s\n", s.t, s.lexeme) v, err := parse(c)
} switch err {
case io.EOF:
return
case nil:
eval(v)
default:
fmt.Println("error in args(): %v", err)
}
}
} }
func main() { func main() {
@ -52,8 +139,17 @@ func main() {
c := make(chan token, 32) c := make(chan token, 32)
go lexs(string(line)+"\n", c) go lexs(string(line)+"\n", c)
for s := range c { for {
fmt.Printf("%11s %s\n", s.t, s.lexeme) v, err := parse(c)
} switch err {
case io.EOF:
goto OUT
case nil:
eval(v)
default:
fmt.Println("error in repl: %v", err)
}
}
OUT:
} }
} }

Loading…
Cancel
Save