From e952ea77f51f526a23c29f08c6bab818d9929bf1 Mon Sep 17 00:00:00 2001 From: sgf Date: Fri, 9 Sep 2022 16:51:27 +0300 Subject: [PATCH] new(go): Save bignum calc code. --- bignum-calc/bignum-calc.go | 134 +++++++++++++++++++++++++++++++++++++ bignum-calc/go.mod | 3 + 2 files changed, 137 insertions(+) create mode 100644 bignum-calc/bignum-calc.go create mode 100644 bignum-calc/go.mod diff --git a/bignum-calc/bignum-calc.go b/bignum-calc/bignum-calc.go new file mode 100644 index 0000000..37c36cc --- /dev/null +++ b/bignum-calc/bignum-calc.go @@ -0,0 +1,134 @@ + +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 +} + diff --git a/bignum-calc/go.mod b/bignum-calc/go.mod new file mode 100644 index 0000000..cabf043 --- /dev/null +++ b/bignum-calc/go.mod @@ -0,0 +1,3 @@ +module bignum-calc + +go 1.15 -- 2.20.1