master
Jordan Orelli 12 years ago
parent 7bf30556ad
commit a3791fcc0e

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

@ -2,13 +2,92 @@ package main
import (
"bufio"
"errors"
"fmt"
"io"
"os"
"strconv"
)
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() {
filename := os.Args[1]
f, err := os.Open(filename)
@ -21,8 +100,16 @@ func args() {
c := make(chan token, 32)
go lex(bufio.NewReader(f), c)
for s := range c {
fmt.Printf("%11s %s\n", s.t, s.lexeme)
for {
v, err := parse(c)
switch err {
case io.EOF:
return
case nil:
eval(v)
default:
fmt.Println("error in args(): %v", err)
}
}
}
@ -52,8 +139,17 @@ func main() {
c := make(chan token, 32)
go lexs(string(line)+"\n", c)
for s := range c {
fmt.Printf("%11s %s\n", s.t, s.lexeme)
for {
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