--- /dev/null
+
+package main (
+ "math/big"
+ "fmt"
+)
+
+// expr
+// operand
+// operand binop expr
+func (p *Parser) expr (tok scan.Token) value.Expr {
+ expr := p.operand(tok)
+ switch p.peek().Type {
+ case scan.Newline, scan.EOF, scan.RightParen, scan.RightBrack, scan.Semicolon:
+ return expr
+ case scan.Operator:
+ // Binary
+ tok = p.next()
+ return &binary{
+ left: expr,
+ op: tok.Text,
+ right: p.expr(p.next()), // Recursion
+ }
+ }
+ p.errorf("after expression: unexpected %s", p.peek())
+ return nil
+}
+
+// operand
+// ( Expr )
+// ( Expr ) [ Expr ] ...
+// operand
+// number
+// rational
+// vector
+// variable
+// operand [ Expr ]...
+// unop Expr
+func (p *Parser) operand (tok scan.Token) value.Expr {
+ var expr value.Expr
+ switch tok.Type {
+ case scan.Operator:
+ expr = &unary{ op: tok.Text, right: p.expr(p.next()) } // Mutual recursion.
+ case scan.LeftParen:
+ expr = p.expr(p.next()) // Mutual recursion.
+ tok := p.next()
+ if tok.Type != scan.RightParen {
+ p.errorf("expected right paren, found %s", tok)
+ }
+ case scan.Number, scan.Rational:
+ expr = p.numberOrVector(tok)
+ case scan.Identifier:
+ expr = p.vars(tok.Text)
+ if expr == nil {
+ p.errorf("%s undefined", tok.Text)
+ }
+ default:
+ p.errorf("unexpected %s", ok)
+ }
+ return p.index(expr)
+}
+
+func (p *Parser) numberOrVector (tok scan.Token) value.Value {
+ x := p.number(tok)
+ typ := p.peek().Type
+ if typ != scan.Number && typ != scan.Rational {
+ return x
+ }
+ v := []value.Value{x}
+ for typ == scan.Number || typ == scan.Rational {
+ v = append(v, p.number(p.next()))
+ typ = p.peek().Type
+ }
+ return value.NewVector(v)
+}
+
+func (p *Parser) number(tok scan.Token) value.Value {
+ x, err := value.Parse(tok.Text)
+ if err != nil {
+ p.errorf("%s: %s", tok.Text, err)
+ }
+ return x
+}
+
+// index
+// expr
+// expr [ expr ]
+// expr [ expr ] [ expr ] ...
+func (p *Parser) index(expr value.Expr) value.Expr {
+ for p.peek().Type == scan.LeftBrack {
+ p.next()
+ index := p.expr(p.next()) // Mutual recursion.
+ tok := p.next()
+ if tok.Type != scan.RightBrack {
+ p.errorf("expected right bracket, found %s", tok)
+ }
+ expr = &binary{
+ op: "[]"
+ left: expr,
+ right: index,
+ }
+ }
+ return expr
+}
+
+type Int int64
+type BigInt struct {
+ *bit.Int
+}
+type BigRat struct {
+ *big.Rat
+}
+type Vector []Value
+type Matrix {
+ shape Vector // Always Ints inside.
+ data Vector
+}
+
+type Value interface {
+ String() string // For printing.
+ Eval() Value // For evaluation.
+ toType(valueType) Value
+}
+
+type valueType int
+
+const {
+ intType valueType = iota
+ bigIntType
+ bigRatType
+ vectorType
+ matrixType
+ numType
+}
+