Just another update
This commit is contained in:
parent
a25938f123
commit
00a190b0a6
6591 changed files with 94363 additions and 23227 deletions
|
|
@ -9,15 +9,15 @@
|
|||
collect (read-char stream) into digits
|
||||
finally (return (parse-integer (coerce digits 'string))))))
|
||||
(consume-whitespace)
|
||||
(let ((c (peek-char nil stream nil nil)))
|
||||
(let ((token (case c
|
||||
((nil) nil)
|
||||
((#\() :lparen)
|
||||
((#\)) :rparen)
|
||||
((#\*) '*)
|
||||
((#\/) '/)
|
||||
((#\+) '+)
|
||||
((#\-) '-)
|
||||
(let* ((c (peek-char nil stream nil nil)))
|
||||
(token (case c
|
||||
(nil nil)
|
||||
(#\( :lparen)
|
||||
(#\) :rparen)
|
||||
(#\* '*)
|
||||
(#\/ '/)
|
||||
(#\+ '+)
|
||||
(#\- '-)
|
||||
(otherwise
|
||||
(unless (digit-char-p c)
|
||||
(cerror "Skip it." "Unexpected character ~w." c)
|
||||
|
|
@ -27,7 +27,7 @@
|
|||
(read-integer)))))
|
||||
(unless (or (null token) (integerp token))
|
||||
(read-char stream))
|
||||
token))))
|
||||
token)))
|
||||
|
||||
(defun group-parentheses (tokens &optional (delimited nil))
|
||||
(do ((new-tokens '()))
|
||||
|
|
@ -37,12 +37,12 @@
|
|||
(values (nreverse new-tokens) '()))
|
||||
(let ((token (pop tokens)))
|
||||
(case token
|
||||
((:lparen)
|
||||
(:lparen
|
||||
(multiple-value-bind (group remaining-tokens)
|
||||
(group-parentheses tokens t)
|
||||
(setf new-tokens (cons group new-tokens)
|
||||
tokens remaining-tokens)))
|
||||
((:rparen)
|
||||
(:rparen
|
||||
(if (not delimited)
|
||||
(cerror "Ignore it." "Unexpected right parenthesis.")
|
||||
(return (values (nreverse new-tokens) tokens))))
|
||||
|
|
|
|||
|
|
@ -4,12 +4,13 @@ import std.stdio, std.string, std.ascii, std.conv, std.array,
|
|||
struct Stack(T) {
|
||||
T[] data;
|
||||
alias data this;
|
||||
void push(T top) pure nothrow { data ~= top; }
|
||||
void push(T top) pure nothrow @safe { data ~= top; }
|
||||
|
||||
T pop(bool discard = true)() pure {
|
||||
T pop(bool discard = true)() pure @nogc @safe {
|
||||
immutable static exc = new immutable(Exception)("Stack Empty");
|
||||
if (data.empty)
|
||||
throw new Exception("Stack Empty");
|
||||
auto top = data.back;
|
||||
throw exc;
|
||||
auto top = data[$ - 1];
|
||||
static if (discard)
|
||||
data.popBack;
|
||||
return top;
|
||||
|
|
@ -20,7 +21,7 @@ enum Type { Num, OBkt, CBkt, Add, Sub, Mul, Div }
|
|||
immutable opChar = ["#", "(", ")", "+", "-", "*", "/"];
|
||||
immutable opPrec = [ 0, -9, -9, 1, 1, 2, 2];
|
||||
|
||||
abstract class Visitor { void visit(XP e); }
|
||||
abstract class Visitor { void visit(XP e) pure @safe; }
|
||||
|
||||
final class XP {
|
||||
immutable Type type;
|
||||
|
|
@ -28,7 +29,7 @@ final class XP {
|
|||
immutable int pos; // Optional, to dispaly AST struct.
|
||||
XP LHS, RHS;
|
||||
|
||||
this(string s=")", int p = -1) nothrow {
|
||||
this(string s=")", int p = -1) pure nothrow @safe {
|
||||
str = s;
|
||||
pos = p;
|
||||
auto localType = Type.Num;
|
||||
|
|
@ -38,13 +39,13 @@ final class XP {
|
|||
this.type = localType;
|
||||
}
|
||||
|
||||
override int opCmp(Object other) pure {
|
||||
override int opCmp(Object other) pure @safe {
|
||||
auto rhs = cast(XP)other;
|
||||
enforce(rhs !is null);
|
||||
return opPrec[type] - opPrec[rhs.type];
|
||||
}
|
||||
|
||||
void accept(Visitor v) { v.visit(this); }
|
||||
void accept(Visitor v) pure @safe { v.visit(this); }
|
||||
}
|
||||
|
||||
final class AST {
|
||||
|
|
@ -53,13 +54,13 @@ final class AST {
|
|||
string xpr, token;
|
||||
int xpHead, xpTail;
|
||||
|
||||
void joinXP(XP x) pure {
|
||||
void joinXP(XP x) pure @safe {
|
||||
x.RHS = num.pop;
|
||||
x.LHS = num.pop;
|
||||
num.push(x);
|
||||
}
|
||||
|
||||
string nextToken() pure {
|
||||
string nextToken() pure @safe {
|
||||
while (xpHead < xpr.length && xpr[xpHead] == ' ')
|
||||
xpHead++; // Skip spc.
|
||||
xpTail = xpHead;
|
||||
|
|
@ -82,7 +83,7 @@ final class AST {
|
|||
return null;
|
||||
} // End nextToken.
|
||||
|
||||
AST parse(in string s) {
|
||||
AST parse(in string s) /*@safe*/ {
|
||||
bool expectingOP;
|
||||
xpr = s;
|
||||
try {
|
||||
|
|
@ -147,7 +148,7 @@ final class AST {
|
|||
|
||||
// To display AST fancy struct.
|
||||
void ins(ref char[][] s, in string v, in int p, in int l)
|
||||
pure nothrow {
|
||||
pure nothrow @safe {
|
||||
if (l + 1 > s.length)
|
||||
s.length++;
|
||||
while (s[l].length < p + v.length + 1)
|
||||
|
|
@ -160,7 +161,7 @@ final class CalcVis : Visitor {
|
|||
string resultStr;
|
||||
char[][] Tree;
|
||||
|
||||
static void opCall(AST a) {
|
||||
static void opCall(AST a) @safe {
|
||||
if (a && a.root) {
|
||||
auto c = new CalcVis;
|
||||
a.root.accept(c);
|
||||
|
|
@ -187,7 +188,7 @@ final class CalcVis : Visitor {
|
|||
}
|
||||
|
||||
// Calc. the value, display AST struct and eval order.
|
||||
override void visit(XP xp) {
|
||||
override void visit(XP xp) @safe {
|
||||
ins(Tree, xp.str, xp.pos, level);
|
||||
level++;
|
||||
if (xp.type == Type.Num) {
|
||||
|
|
@ -212,9 +213,9 @@ final class CalcVis : Visitor {
|
|||
}
|
||||
}
|
||||
|
||||
void main(string[] args) {
|
||||
void main(string[] args) /*@safe*/ {
|
||||
immutable exp0 = "1 + 2*(3 - 2*(3 - 2)*((2 - 4)*5" ~
|
||||
" - 22/(7 + 2*(3 - 1)) - 1)) + 1";
|
||||
immutable exp = (args.length > 1) ? args[1 .. $].join(" ") : exp0;
|
||||
immutable exp = (args.length > 1) ? args[1 .. $].join(' ') : exp0;
|
||||
new AST().parse(exp).CalcVis; // Should be 60.
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
^ aNode += self.
|
||||
]
|
||||
|
||||
#method Number = convertor toReal:theValue.
|
||||
#method Number = convertor toReal:(theValue value).
|
||||
}
|
||||
|
||||
// --- Node ---
|
||||
|
|
@ -294,7 +294,7 @@
|
|||
#var aParser := Parser new.
|
||||
|
||||
consoleEx writeLine:"=" :(aParser foreach:aText Number)
|
||||
| ifFailed:
|
||||
| if &e:
|
||||
[
|
||||
consoleEx writeLine:"Invalid Expression".
|
||||
].
|
||||
|
|
|
|||
|
|
@ -20,4 +20,4 @@
|
|||
((num? X) X)
|
||||
((= "+" X) (term))
|
||||
((= "-" X) (list '- (term)))
|
||||
((= "(" X) (prog1 (aggregate) (pop '*L)))) ) ) )
|
||||
((= "(" X) (prog1 (aggregate) (pop '*L)))) ) )
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ j=0; do forever; j=j+1; if j>L then leave; _=substr(x,j,1); _2=getX()
|
|||
end /* 2nd symbol.*/
|
||||
z=z _ $; iterate
|
||||
end
|
||||
if _=='+' | _=="-" then do; p_=word(z,words(z)) /*last Z token*/
|
||||
if p_=='(' then z=z 0 /*handle unary±*/
|
||||
if _=='+' | _=="-" then do; p_=word(z,words(z)) /*last Z token*/
|
||||
if p_=='(' then z=z 0 /*handle unary ±*/
|
||||
z=z _ $; iterate
|
||||
end
|
||||
lets=0; sigs=0; #=_
|
||||
|
|
@ -24,17 +24,17 @@ j=0; do forever; j=j+1; if j>L then leave; _=substr(x,j,1); _2=getX()
|
|||
if lets==1 & sigs==0 then if _=='+' | _=='-' then do; sigs=1
|
||||
#=# || _
|
||||
iterate
|
||||
end /*exp*/
|
||||
end
|
||||
if pos(_,nchars)==0 then leave
|
||||
lets=lets+datatype(_,'M') /*keep track of # of exponents. */
|
||||
#=# || translate(_,'EEEEE','eDdQq') /*keep building the num*/
|
||||
#=# || translate(_,'EEEEE','eDdQq') /*keep buildingthe num.*/
|
||||
end /*j*/
|
||||
j=j-1
|
||||
if \datatype(#,'N') then call serr 'invalid number: ' #
|
||||
if \datatype(#,'N') then call serr 'invalid number: ' #
|
||||
z=z # $
|
||||
end /*forever*/
|
||||
|
||||
_=word(z,1); if _=='+' | _=='-' then z=0 z /*handle unary cases.*/
|
||||
_=word(z,1); if _=='+' | _=='-' then z=0 z /*handle unary cases.*/
|
||||
x='(' space(z) ') '; tokens=words(x) /*force stacking for expression. */
|
||||
do i=1 for tokens; @.i=word(x,i); end /*i*/ /*assign input tokens*/
|
||||
L=max(20,length(x)) /*use 20 for the min show width. */
|
||||
|
|
@ -104,7 +104,7 @@ z=space(z stack) /*append any residual entries. */
|
|||
say 'answer──►' z /*display the answer (result). */
|
||||
parse source upper . how . /*invoked via C.L. or REXX pgm?*/
|
||||
if how=='COMMAND' | ,
|
||||
\datatype(z,'W') then exit /*stick a fork in it, we're done.*/
|
||||
\datatype(z,'W') then exit /*stick a fork in it, we're done.*/
|
||||
return z /*return Z ──► invoker (RESULT).*/
|
||||
/*──────────────────────────────────subroutines─────────────────────────*/
|
||||
isBit: return arg(1)==0 | arg(1)==1 /*returns 1 if arg1 is bin bit.*/
|
||||
|
|
@ -112,6 +112,6 @@ isOp: return pos(arg(1),rOp)\==0 /*is argument1 a "real" operator?*/
|
|||
serr: say; say e arg(1); say; exit 13 /*issue an error message with txt*/
|
||||
/*──────────────────────────────────GETX subroutine─────────────────────*/
|
||||
getX: do Nj=j+1 to length(x); _n=substr(x,Nj,1); if _n==$ then iterate
|
||||
if _n==$ then iterate; return substr(x,Nj,1) /*ignore blanks*/
|
||||
return substr(x,Nj,1) /* [↑] ignore any blanks in exp.*/
|
||||
end /*Nj*/
|
||||
return $ /*reached end-of-tokens, return $*/
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
$op_priority = {"+" => 0, "-" => 0, "*" => 1, "/" => 1}
|
||||
$op_function = {
|
||||
"+" => lambda {|x, y| x + y},
|
||||
"-" => lambda {|x, y| x - y},
|
||||
"*" => lambda {|x, y| x * y},
|
||||
"/" => lambda {|x, y| x / y}}
|
||||
|
||||
class TreeNode
|
||||
OP_FUNCTION = {
|
||||
"+" => lambda {|x, y| x + y},
|
||||
"-" => lambda {|x, y| x - y},
|
||||
"*" => lambda {|x, y| x * y},
|
||||
"/" => lambda {|x, y| x / y}}
|
||||
attr_accessor :info, :left, :right
|
||||
|
||||
def initialize(info)
|
||||
|
|
@ -23,10 +23,10 @@ class TreeNode
|
|||
left_s, right_s = @left.to_s(order), @right.to_s(order)
|
||||
|
||||
strs = case order
|
||||
when :prefix then [@info, left_s, right_s]
|
||||
when :infix then [left_s, @info, right_s]
|
||||
when :prefix then [@info, left_s, right_s]
|
||||
when :infix then [left_s, @info, right_s]
|
||||
when :postfix then [left_s, right_s, @info]
|
||||
else []
|
||||
else []
|
||||
end
|
||||
|
||||
"(" + strs.join(" ") + ")"
|
||||
|
|
@ -35,7 +35,7 @@ class TreeNode
|
|||
|
||||
def eval
|
||||
if !leaf? and operator?(@info)
|
||||
$op_function[@info].call(@left.eval, @right.eval)
|
||||
OP_FUNCTION[@info].call(@left.eval, @right.eval)
|
||||
else
|
||||
@info.to_f
|
||||
end
|
||||
|
|
@ -46,6 +46,10 @@ def tokenize(exp)
|
|||
exp
|
||||
.gsub('(', ' ( ')
|
||||
.gsub(')', ' ) ')
|
||||
.gsub('+', ' + ')
|
||||
.gsub('-', ' - ')
|
||||
.gsub('*', ' * ')
|
||||
.gsub('/', ' / ')
|
||||
.split(' ')
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue