|
|
@ -2,7 +2,7 @@ package main
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
import (
|
|
|
|
"bufio"
|
|
|
|
"bufio"
|
|
|
|
"errors"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"io"
|
|
|
|
"os"
|
|
|
|
"os"
|
|
|
@ -17,75 +17,89 @@ type symbol string
|
|
|
|
|
|
|
|
|
|
|
|
// parses the string lexeme into a value that can be eval'd
|
|
|
|
// parses the string lexeme into a value that can be eval'd
|
|
|
|
func atom(t token) (interface{}, error) {
|
|
|
|
func atom(t token) (interface{}, error) {
|
|
|
|
switch t.t {
|
|
|
|
switch t.t {
|
|
|
|
case integerToken:
|
|
|
|
case integerToken:
|
|
|
|
val, err := strconv.ParseInt(t.lexeme, 10, 64)
|
|
|
|
val, err := strconv.ParseInt(t.lexeme, 10, 64)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return val, nil
|
|
|
|
return val, nil
|
|
|
|
|
|
|
|
|
|
|
|
case floatToken:
|
|
|
|
case floatToken:
|
|
|
|
val, err := strconv.ParseFloat(t.lexeme, 64)
|
|
|
|
val, err := strconv.ParseFloat(t.lexeme, 64)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return val, nil
|
|
|
|
return val, nil
|
|
|
|
|
|
|
|
|
|
|
|
case stringToken:
|
|
|
|
case stringToken:
|
|
|
|
return t.lexeme, nil
|
|
|
|
return t.lexeme, nil
|
|
|
|
|
|
|
|
|
|
|
|
case symbolToken:
|
|
|
|
case symbolToken:
|
|
|
|
return symbol(t.lexeme), nil
|
|
|
|
return symbol(t.lexeme), nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return nil, fmt.Errorf("unable to atomize token: %v", t)
|
|
|
|
return nil, fmt.Errorf("unable to atomize token: %v", t)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// reads in tokens on the channel until a matching close paren is found.
|
|
|
|
// reads in tokens on the channel until a matching close paren is found.
|
|
|
|
func (s *sexp) readIn(c chan token) error {
|
|
|
|
func (s *sexp) readIn(c chan token) error {
|
|
|
|
for t := range c {
|
|
|
|
for t := range c {
|
|
|
|
switch t.t {
|
|
|
|
switch t.t {
|
|
|
|
case closeParenToken:
|
|
|
|
case closeParenToken:
|
|
|
|
return nil
|
|
|
|
return nil
|
|
|
|
case openParenToken:
|
|
|
|
case openParenToken:
|
|
|
|
child := make(sexp, 0)
|
|
|
|
child := make(sexp, 0)
|
|
|
|
if err := child.readIn(c); err != nil {
|
|
|
|
if err := child.readIn(c); err != nil {
|
|
|
|
return err
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*s = append(*s, child)
|
|
|
|
*s = append(*s, child)
|
|
|
|
default:
|
|
|
|
default:
|
|
|
|
v, err := atom(t)
|
|
|
|
v, err := atom(t)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*s = append(*s, v)
|
|
|
|
*s = append(*s, v)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return errors.New("unexpected EOF in sexp.readIn")
|
|
|
|
return errors.New("unexpected EOF in sexp.readIn")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// parses one value that can be evaled from the channel
|
|
|
|
// parses one value that can be evaled from the channel
|
|
|
|
func parse(c chan token) (interface{}, error) {
|
|
|
|
func parse(c chan token) (interface{}, error) {
|
|
|
|
for t := range c {
|
|
|
|
for t := range c {
|
|
|
|
switch t.t {
|
|
|
|
switch t.t {
|
|
|
|
case closeParenToken:
|
|
|
|
case closeParenToken:
|
|
|
|
return nil, errors.New("unexpected EOF in read")
|
|
|
|
return nil, errors.New("unexpected EOF in read")
|
|
|
|
case openParenToken:
|
|
|
|
case openParenToken:
|
|
|
|
s := make(sexp, 0)
|
|
|
|
s := make(sexp, 0)
|
|
|
|
if err := s.readIn(c); err != nil {
|
|
|
|
if err := s.readIn(c); err != nil {
|
|
|
|
return nil, err
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return s, nil
|
|
|
|
return s, nil
|
|
|
|
default:
|
|
|
|
default:
|
|
|
|
return atom(t)
|
|
|
|
return atom(t)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil, io.EOF
|
|
|
|
return nil, io.EOF
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func eval(v interface{}) {
|
|
|
|
func eval(v interface{}) {
|
|
|
|
fmt.Println(v)
|
|
|
|
fmt.Println(v)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func evalall(c chan token) {
|
|
|
|
|
|
|
|
for {
|
|
|
|
|
|
|
|
v, err := parse(c)
|
|
|
|
|
|
|
|
switch err {
|
|
|
|
|
|
|
|
case io.EOF:
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
case nil:
|
|
|
|
|
|
|
|
eval(v)
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
fmt.Println("error in eval: %v", err)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func args() {
|
|
|
|
func args() {
|
|
|
@ -99,18 +113,7 @@ func args() {
|
|
|
|
|
|
|
|
|
|
|
|
c := make(chan token, 32)
|
|
|
|
c := make(chan token, 32)
|
|
|
|
go lex(bufio.NewReader(f), c)
|
|
|
|
go lex(bufio.NewReader(f), c)
|
|
|
|
|
|
|
|
evalall(c)
|
|
|
|
for {
|
|
|
|
|
|
|
|
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() {
|
|
|
@ -139,17 +142,6 @@ 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 {
|
|
|
|
evalall(c)
|
|
|
|
v, err := parse(c)
|
|
|
|
|
|
|
|
switch err {
|
|
|
|
|
|
|
|
case io.EOF:
|
|
|
|
|
|
|
|
goto OUT
|
|
|
|
|
|
|
|
case nil:
|
|
|
|
|
|
|
|
eval(v)
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
fmt.Println("error in repl: %v", err)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
OUT:
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|