Line data Source code
1 : import 'dart:math';
2 : import 'package:clc/fract.dart';
3 : import 'package:clc/rpn.dart';
4 :
5 : class FractRpn extends RPN<Fraction> {
6 6 : static RegExp numberExp = RegExp(r"[0-9]+(\.[0-9]+)?(e[\+\-])?[0-9]*");
7 6 : static RegExp funcExp = RegExp(r"[a-zA-Z][a-zA-Z0-9]*");
8 0 : static Map<String, Fraction> constants = {
9 0 : "pi": Fraction.fromDouble(pi),
10 0 : "e": Fraction.fromDouble(e),
11 : };
12 :
13 2 : @override
14 : void exec1(String v) {
15 : Set<String> ary1 = {
16 2 : "S-",
17 2 : "S+",
18 2 : "S!",
19 2 : "log",
20 2 : "log2",
21 2 : "log10",
22 2 : "sqrt",
23 2 : "exp"
24 : };
25 18 : Set<String> ary2 = {"+", "-", "*", "×", "/", "÷", "<<", ">>", "%"};
26 4 : if (numberExp.matchAsPrefix(v) != null) {
27 4 : push(Fraction.fromString(v));
28 2 : } else if (ary1.contains(v)) {
29 1 : var a = pop();
30 : if (a == null) {
31 0 : log.e("pop null(1)");
32 : return;
33 : }
34 1 : if (v == "S-") {
35 2 : push(-a);
36 1 : } else if (v == "S+") {
37 1 : push(a);
38 1 : } else if (v == "S!") {
39 1 : var res = BigInt.one;
40 5 : for (var i = a.toBigInt(); i > BigInt.one; i -= BigInt.one) {
41 1 : res *= i;
42 : }
43 2 : push(Fraction.fromBigInt(res));
44 0 : } else if (v == "log") {
45 0 : push(a.log());
46 0 : } else if (v == "log2") {
47 0 : push(a.log2());
48 0 : } else if (v == "log10") {
49 0 : push(a.log10());
50 0 : } else if (v == "exp") {
51 0 : push(a.exp());
52 0 : } else if (v == "sqrt") {
53 0 : push(a.sqrt());
54 : } else {
55 0 : throw Exception("no such unary op: $v");
56 : }
57 2 : } else if (ary2.contains(v)) {
58 2 : var a = pop();
59 : if (a == null) {
60 0 : log.e("pop null(a)");
61 : return;
62 : }
63 2 : var b = pop();
64 : if (b == null) {
65 2 : log.e("pop null(b)");
66 : return;
67 : }
68 2 : if (v == "+") {
69 4 : push(b + a);
70 2 : } else if (v == "-") {
71 2 : push(b - a);
72 4 : } else if (v == "*" || v == "×") {
73 2 : push(b * a);
74 4 : } else if (v == "/" || v == "÷") {
75 4 : push(b / a);
76 1 : } else if (v == "<<") {
77 4 : push(b << a.toBigInt().toInt());
78 1 : } else if (v == ">>") {
79 4 : push(b >> a.toBigInt().toInt());
80 0 : } else if (v == "%") {
81 0 : push(b % a);
82 : } else {
83 0 : throw Exception("no such binary op: $v");
84 : }
85 : }
86 : }
87 :
88 2 : Fraction? eval(String s) {
89 6 : fromInfixString(s, numberExp, funcExp);
90 2 : return evaluate();
91 : }
92 :
93 : List<String> exprStack = [];
94 :
95 2 : void toExpr1(String v) {
96 : Set<String> ary1 = {
97 2 : "S-",
98 2 : "S+",
99 2 : "S!",
100 2 : "log",
101 2 : "log2",
102 2 : "log10",
103 2 : "sqrt",
104 2 : "exp"
105 : };
106 18 : Set<String> ary2 = {"+", "-", "*", "×", "/", "÷", "<<", ">>", "%"};
107 4 : if (numberExp.matchAsPrefix(v) != null) {
108 8 : exprStack.add(Fraction.fromString(v).toExpr());
109 2 : } else if (ary1.contains(v)) {
110 2 : var a = exprStack.removeLast();
111 1 : if (a.contains(" ")) {
112 1 : a = "($a)";
113 : }
114 1 : if (v == "S-") {
115 0 : exprStack.add("-$a");
116 1 : } else if (v == "S+") {
117 0 : exprStack.add("+$a");
118 1 : } else if (v == "S!") {
119 3 : exprStack.add("$a!");
120 1 : } else if (v == "log") {
121 3 : exprStack.add("\\log $a");
122 0 : } else if (v == "log2") {
123 0 : exprStack.add("\\log_2 $a");
124 0 : } else if (v == "log10") {
125 0 : exprStack.add("\\log_10 $a");
126 0 : } else if (v == "exp") {
127 0 : exprStack.add("e^{$a}");
128 0 : } else if (v == "sqrt") {
129 0 : exprStack.add("\\sqrt{$a}");
130 : } else {
131 0 : throw Exception("no such unary op: $v");
132 : }
133 2 : } else if (ary2.contains(v)) {
134 4 : var a = exprStack.removeLast();
135 4 : var b = exprStack.removeLast();
136 2 : if (a.contains(" ")) {
137 0 : a = "($a)";
138 : }
139 2 : if (b.contains(" ")) {
140 0 : b = "($b)";
141 : }
142 2 : if (v == "+") {
143 6 : exprStack.add("$b + $a");
144 2 : } else if (v == "-") {
145 0 : exprStack.add("$b - $a");
146 4 : } else if (v == "*" || v == "×") {
147 0 : exprStack.add("$b \\times $a");
148 3 : } else if (v == "/" || v == "÷") {
149 6 : exprStack.add("\\frac{$b}{$a}");
150 0 : } else if (v == "<<") {
151 0 : exprStack.add("$b << $a");
152 0 : } else if (v == ">>") {
153 0 : exprStack.add("$b >> $a");
154 0 : } else if (v == "%") {
155 0 : exprStack.add("$b \\bmod $a");
156 : } else {
157 0 : throw Exception("no such binary op: $v");
158 : }
159 : }
160 : }
161 :
162 2 : String toExpr() {
163 4 : exprStack = [];
164 4 : for (var x in expression) {
165 2 : toExpr1(x);
166 : }
167 4 : return exprStack.last;
168 : }
169 : }
|