Exemplo n.º 1
0
// Parse scans given tokens and return it into expression.
func (p *Parser) Parse() (exps types.Expression, err error) {
	token, err := p.lex.Next()
	if err != nil {
		return nil, err
	}

	switch token {
	case "'":
		// if start with (, deal as list.
		// recursive scan until ")"
		// if start with "'(", it's list.
		if p.lex.Peek() == '(' {
			// this is (. skip it.
			if _, err := p.lex.Next(); err != nil {
				return nil, err
			}
			tokens, err := p.parseList()
			if err != nil {
				return nil, err
			}
			return types.NewList(tokens...), nil
		}
		// if not start with (, it's simply string (return string itself).
		t, err := p.lex.Next()
		if err != nil {
			return nil, err
		}
		return types.Symbol(t), nil
	case "(":
		// start S-Expression. Parse as list.
		return p.parseList()
	case ")":
		return nil, errors.New("unexpected ')'")
	case "#t":
		return types.Boolean(true), nil
	case "#f":
		return types.Boolean(false), nil
	default:
		// if token is string, get unquoted.
		// It's get test from \"test\".
		if p.lex.IsTokenString() {
			return strconv.Unquote(p.lex.TokenText())
		}
		// try conversion to float. if failed, treated as symbol.
		if n, err := strconv.ParseFloat(token, 64); err == nil {
			return types.Number(n), nil
		}
		return types.Symbol(token), nil
	}
}
Exemplo n.º 2
0
func TestParseDash(t *testing.T) {
	r := strings.NewReader("(define a-b-c-efg x)")
	parser := New(lexer.New(r))
	actual := []types.Expression{
		types.Symbol("define"),
		types.Symbol("a-b-c-efg"),
		types.Symbol("x"),
	}
	exps, err := parser.Parse()
	if err != nil {
		t.Fatalf("parser failed: %s", err)
	}
	if !reflect.DeepEqual(exps, actual) {
		t.Fatalf("expressions is not expected. %#v", exps)
	}
}
Exemplo n.º 3
0
func TestQuote(t *testing.T) {
	r := strings.NewReader("'hello")
	parser := New(lexer.New(r))
	actual := types.Symbol("hello")
	exps, err := parser.Parse()
	if err != nil {
		t.Fatalf("parser failed: %s", err)
	}
	if !reflect.DeepEqual(exps, actual) {
		t.Fatalf("expressions is not expected. %v", exps)
	}
}
Exemplo n.º 4
0
func TestParseString(t *testing.T) {
	r := strings.NewReader("(print \"it's test\")")
	parser := New(lexer.New(r))
	actual := []types.Expression{
		types.Symbol("print"),
		"it's test",
	}
	exps, err := parser.Parse()
	if err != nil {
		t.Fatalf("parser failed: %s", err)
	}
	if !reflect.DeepEqual(exps, actual) {
		t.Fatalf("expressions is not expected. %#v", exps)
	}
}
Exemplo n.º 5
0
func TestNewLine(t *testing.T) {
	r := strings.NewReader("(print 1)\n\n")
	parser := New(lexer.New(r))
	actual := []types.Expression{
		types.Symbol("print"),
		types.Number(1),
	}
	exps, err := parser.Parse()
	if err != nil {
		t.Fatalf("parser failed: %s", err)
	}
	if !reflect.DeepEqual(exps, actual) {
		t.Fatalf("expressions is not expected. %v", exps)
	}
}
Exemplo n.º 6
0
func evalCond(exps []types.Expression, env *Env) (types.Expression, error) {
	for _, operand := range exps[1:] {
		tt, ok := operand.([]types.Expression)
		if !ok {
			return nil, errors.New("cond clause must have expression")
		}
		if tt[0] == types.Symbol("else") {
			return Eval(tt[1], env)
		}
		if bb, err := evalPredicate(tt[0], env); err != nil {
			return nil, err
		} else if bb {
			return Eval(tt[1], env)
		}
	}
	// unreachable
	return nil, nil
}
Exemplo n.º 7
0
// Eval is body of evaluator
func Eval(exp types.Expression, env *Env) (types.Expression, error) {
	switch t := exp.(type) {
	case types.Boolean, types.Number, *types.Pair, string:
		return t, nil
	case types.Symbol:
		// it's variable or expression. get value from environment
		e, err := env.Get(t)
		if err != nil {
			return nil, err
		}
		return e, nil
	case []types.Expression:
		if len(t) == 0 {
			return &types.Pair{}, nil
		}
		switch t[0] {
		case types.Symbol("define"):
			return evalDefine(t, env)
		case types.Symbol("if"):
			if len(t) < 4 {
				return nil, errors.New("syntax error: if clause must be (if predicate consequent alternative) style")
			}
			return evalIf(t[1], t[2], t[3], env)
		case types.Symbol("cond"):
			if len(t) < 2 {
				return nil, errors.New("syntax error: cond clause must be (cond predicate consequent alternative) style")
			}
			return evalCond(t, env)
		case types.Symbol("lambda"):
			if len(t) < 3 {
				return nil, errors.New("lambda must have more than 3 words")
			}
			return Lambda{t[1], t[2], env}, nil
		case types.Symbol("begin"):
			return evalBegin(env, t[1:]...)
		case types.Symbol("load"):
			path, ok := t[1].(string)
			if !ok {
				return nil, errors.New("syntax error: args of load should be string")
			}
			return evalLoad(path, env)
		default:
			return evalApplication(env, t[0], t[1:]...)
		}
	default:
		// not found any known operands. failed.
		return nil, fmt.Errorf("unknown expression type -- %v", exp)
	}
}
Exemplo n.º 8
0
// EvalReader evaluate scheme program from io.Reader
func EvalReader(r io.Reader, env *Env) (types.Expression, error) {
	l := lexer.New(r)
	p := parser.New(l)
	if _, err := env.Get("#current-load-path"); err != nil {
		env.Put("#current-load-path", "")
	}
	var exps types.Expression
	for {
		tokens, err := p.Parse()
		if err != nil {
			return nil, err
		}
		// TODO should handle unknown token.
		if tokens == types.Symbol("") {
			break
		}
		exps, err = Eval(tokens, env)
		if err != nil {
			return nil, err
		}
	}
	return exps, nil
}
Exemplo n.º 9
0
func TestParserRecursive(t *testing.T) {
	r := strings.NewReader("(define (square x) (* x x))")
	parser := New(lexer.New(r))
	expected := []types.Expression{
		types.Symbol("define"),
		[]types.Expression{
			types.Symbol("square"),
			types.Symbol("x"),
		},
		[]types.Expression{
			types.Symbol("*"),
			types.Symbol("x"),
			types.Symbol("x"),
		},
	}
	exps, err := parser.Parse()
	if err != nil {
		t.Fatalf("parser failed: %s", err)
	}
	if !reflect.DeepEqual(exps, expected) {
		t.Fatalf("expressions is not expected. %#v", exps)
	}
}
Exemplo n.º 10
0
func TestParseLineDelimited(t *testing.T) {
	r := strings.NewReader(`
(define (fib n)
  (cond ((= n 0) 0)
        ((= n 1) 1)
        (else (+ (fib (- n 1)) (fib (- n 2))))))
	`)
	parser := New(lexer.New(r))
	actual := []types.Expression{
		types.Symbol("define"),
		[]types.Expression{
			types.Symbol("fib"),
			types.Symbol("n"),
		},
		[]types.Expression{
			types.Symbol("cond"),
			[]types.Expression{
				[]types.Expression{
					types.Symbol("="),
					types.Symbol("n"),
					types.Number(0),
				},
				types.Number(0),
			},
			[]types.Expression{
				[]types.Expression{
					types.Symbol("="),
					types.Symbol("n"),
					types.Number(1),
				},
				types.Number(1),
			},
			[]types.Expression{
				types.Symbol("else"),
				[]types.Expression{
					types.Symbol("+"),
					[]types.Expression{
						types.Symbol("fib"),
						[]types.Expression{
							types.Symbol("-"),
							types.Symbol("n"),
							types.Number(1),
						},
					},
					[]types.Expression{
						types.Symbol("fib"),
						[]types.Expression{
							types.Symbol("-"),
							types.Symbol("n"),
							types.Number(2),
						},
					},
				},
			},
		},
	}
	exps, err := parser.Parse()
	if err != nil {
		t.Fatalf("parser failed: %s", err)
	}
	if !reflect.DeepEqual(exps, actual) {
		t.Fatalf("expressions is not expected. %#v", exps)
	}
}