CDE
This commit is contained in:
parent
518da4a923
commit
764da6cbbb
6144 changed files with 83610 additions and 11 deletions
116
Task/Arithmetic-evaluation/C++/arithmetic-evaluation.cpp
Normal file
116
Task/Arithmetic-evaluation/C++/arithmetic-evaluation.cpp
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
#include <boost/spirit.hpp>
|
||||
#include <boost/spirit/tree/ast.hpp>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <istream>
|
||||
#include <ostream>
|
||||
|
||||
using boost::spirit::rule;
|
||||
using boost::spirit::parser_tag;
|
||||
using boost::spirit::ch_p;
|
||||
using boost::spirit::real_p;
|
||||
|
||||
using boost::spirit::tree_node;
|
||||
using boost::spirit::node_val_data;
|
||||
|
||||
// The grammar
|
||||
struct parser: public boost::spirit::grammar<parser>
|
||||
{
|
||||
enum rule_ids { addsub_id, multdiv_id, value_id, real_id };
|
||||
|
||||
struct set_value
|
||||
{
|
||||
set_value(parser const& p): self(p) {}
|
||||
void operator()(tree_node<node_val_data<std::string::iterator,
|
||||
double> >& node,
|
||||
std::string::iterator begin,
|
||||
std::string::iterator end) const
|
||||
{
|
||||
node.value.value(self.tmp);
|
||||
}
|
||||
parser const& self;
|
||||
};
|
||||
|
||||
mutable double tmp;
|
||||
|
||||
template<typename Scanner> struct definition
|
||||
{
|
||||
rule<Scanner, parser_tag<addsub_id> > addsub;
|
||||
rule<Scanner, parser_tag<multdiv_id> > multdiv;
|
||||
rule<Scanner, parser_tag<value_id> > value;
|
||||
rule<Scanner, parser_tag<real_id> > real;
|
||||
|
||||
definition(parser const& self)
|
||||
{
|
||||
using namespace boost::spirit;
|
||||
addsub = multdiv
|
||||
>> *((root_node_d[ch_p('+')] | root_node_d[ch_p('-')]) >> multdiv);
|
||||
multdiv = value
|
||||
>> *((root_node_d[ch_p('*')] | root_node_d[ch_p('/')]) >> value);
|
||||
value = real | inner_node_d[('(' >> addsub >> ')')];
|
||||
real = leaf_node_d[access_node_d[real_p[assign_a(self.tmp)]][set_value(self)]];
|
||||
}
|
||||
|
||||
rule<Scanner, parser_tag<addsub_id> > const& start() const
|
||||
{
|
||||
return addsub;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template<typename TreeIter>
|
||||
double evaluate(TreeIter const& i)
|
||||
{
|
||||
double op1, op2;
|
||||
switch (i->value.id().to_long())
|
||||
{
|
||||
case parser::real_id:
|
||||
return i->value.value();
|
||||
case parser::value_id:
|
||||
case parser::addsub_id:
|
||||
case parser::multdiv_id:
|
||||
op1 = evaluate(i->children.begin());
|
||||
op2 = evaluate(i->children.begin()+1);
|
||||
switch(*i->value.begin())
|
||||
{
|
||||
case '+':
|
||||
return op1 + op2;
|
||||
case '-':
|
||||
return op1 - op2;
|
||||
case '*':
|
||||
return op1 * op2;
|
||||
case '/':
|
||||
return op1 / op2;
|
||||
default:
|
||||
assert(!"Should not happen");
|
||||
}
|
||||
default:
|
||||
assert(!"Should not happen");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// the read/eval/write loop
|
||||
int main()
|
||||
{
|
||||
parser eval;
|
||||
std::string line;
|
||||
while (std::cout << "Expression: "
|
||||
&& std::getline(std::cin, line)
|
||||
&& !line.empty())
|
||||
{
|
||||
typedef boost::spirit::node_val_data_factory<double> factory_t;
|
||||
boost::spirit::tree_parse_info<std::string::iterator, factory_t> info =
|
||||
boost::spirit::ast_parse<factory_t>(line.begin(), line.end(),
|
||||
eval, boost::spirit::space_p);
|
||||
if (info.full)
|
||||
{
|
||||
std::cout << "Result: " << evaluate(info.trees.begin()) << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Error in expression." << std::endl;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
(defun tokenize-stream (stream)
|
||||
(labels ((whitespace-p (char)
|
||||
(find char #(#\space #\newline #\return #\tab)))
|
||||
(consume-whitespace ()
|
||||
(loop while (whitespace-p (peek-char nil stream nil #\a))
|
||||
do (read-char stream)))
|
||||
(read-integer ()
|
||||
(loop while (digit-char-p (peek-char nil stream nil #\space))
|
||||
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)
|
||||
((#\*) '*)
|
||||
((#\/) '/)
|
||||
((#\+) '+)
|
||||
((#\-) '-)
|
||||
(otherwise
|
||||
(unless (digit-char-p c)
|
||||
(cerror "Skip it." "Unexpected character ~w." c)
|
||||
(read-char stream)
|
||||
(return-from tokenize-stream
|
||||
(tokenize-stream stream)))
|
||||
(read-integer)))))
|
||||
(unless (or (null token) (integerp token))
|
||||
(read-char stream))
|
||||
token))))
|
||||
|
||||
(defun group-parentheses (tokens &optional (delimited nil))
|
||||
(do ((new-tokens '()))
|
||||
((endp tokens)
|
||||
(when delimited
|
||||
(cerror "Insert it." "Expected right parenthesis."))
|
||||
(values (nreverse new-tokens) '()))
|
||||
(let ((token (pop tokens)))
|
||||
(case token
|
||||
((:lparen)
|
||||
(multiple-value-bind (group remaining-tokens)
|
||||
(group-parentheses tokens t)
|
||||
(setf new-tokens (cons group new-tokens)
|
||||
tokens remaining-tokens)))
|
||||
((:rparen)
|
||||
(if (not delimited)
|
||||
(cerror "Ignore it." "Unexpected right parenthesis.")
|
||||
(return (values (nreverse new-tokens) tokens))))
|
||||
(otherwise
|
||||
(push token new-tokens))))))
|
||||
|
||||
(defun group-operations (expression)
|
||||
(flet ((gop (exp) (group-operations exp)))
|
||||
(if (integerp expression)
|
||||
expression
|
||||
(destructuring-bind (a &optional op1 b op2 c &rest others)
|
||||
expression
|
||||
(unless (member op1 '(+ - * / nil))
|
||||
(error "syntax error: in expr ~a expecting operator, not ~a"
|
||||
expression op1))
|
||||
(unless (member op2 '(+ - * / nil))
|
||||
(error "syntax error: in expr ~a expecting operator, not ~a"
|
||||
expression op2))
|
||||
(cond
|
||||
((not op1) (gop a))
|
||||
((not op2) `(,(gop a) ,op1 ,(gop b)))
|
||||
(t (let ((a (gop a)) (b (gop b)) (c (gop c)))
|
||||
(if (and (member op1 '(+ -)) (member op2 '(* /)))
|
||||
(gop `(,a ,op1 (,b ,op2 ,c) ,@others))
|
||||
(gop `((,a ,op1 ,b) ,op2 ,c ,@others))))))))))
|
||||
|
||||
(defun infix-to-prefix (expression)
|
||||
(if (integerp expression)
|
||||
expression
|
||||
(destructuring-bind (a op b) expression
|
||||
`(,op ,(infix-to-prefix a) ,(infix-to-prefix b)))))
|
||||
|
||||
(defun evaluate (string)
|
||||
(with-input-from-string (in string)
|
||||
(eval
|
||||
(infix-to-prefix
|
||||
(group-operations
|
||||
(group-parentheses
|
||||
(loop for token = (tokenize-stream in)
|
||||
until (null token)
|
||||
collect token)))))))
|
||||
219
Task/Arithmetic-evaluation/D/arithmetic-evaluation.d
Normal file
219
Task/Arithmetic-evaluation/D/arithmetic-evaluation.d
Normal file
|
|
@ -0,0 +1,219 @@
|
|||
import std.stdio, std.string, std.ascii, std.conv, std.array,
|
||||
std.exception, std.traits;
|
||||
|
||||
struct Stack(T) {
|
||||
T[] data;
|
||||
alias data this;
|
||||
void push(T top) pure nothrow { data ~= top; }
|
||||
|
||||
T pop(bool discard = true)() pure {
|
||||
if (data.empty)
|
||||
throw new Exception("Stack Empty");
|
||||
auto top = data.back;
|
||||
static if (discard)
|
||||
data.popBack();
|
||||
return top;
|
||||
}
|
||||
}
|
||||
|
||||
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); }
|
||||
|
||||
final class XP {
|
||||
immutable Type type;
|
||||
immutable string str;
|
||||
immutable int pos; // Optional, to dispaly AST struct.
|
||||
XP LHS, RHS;
|
||||
|
||||
this(string s=")", int p = -1) nothrow {
|
||||
str = s;
|
||||
pos = p;
|
||||
type = Type.Num;
|
||||
foreach_reverse (immutable t; [EnumMembers!Type[1 .. $]])
|
||||
if (opChar[t] == s)
|
||||
type = t;
|
||||
}
|
||||
|
||||
override int opCmp(Object other) pure {
|
||||
auto rhs = cast(XP)other;
|
||||
enforce(rhs !is null);
|
||||
return opPrec[type] - opPrec[rhs.type];
|
||||
}
|
||||
|
||||
void accept(Visitor v) { v.visit(this); }
|
||||
}
|
||||
|
||||
final class AST {
|
||||
XP root;
|
||||
Stack!XP opr, num;
|
||||
string xpr, token;
|
||||
int xpHead, xpTail;
|
||||
|
||||
void joinXP(XP x) pure {
|
||||
x.RHS = num.pop();
|
||||
x.LHS = num.pop();
|
||||
num.push(x);
|
||||
}
|
||||
|
||||
string nextToken() pure {
|
||||
while (xpHead < xpr.length && xpr[xpHead] == ' ')
|
||||
xpHead++; // Skip spc.
|
||||
xpTail = xpHead;
|
||||
if (xpHead < xpr.length) {
|
||||
token = xpr[xpTail .. xpTail + 1];
|
||||
switch (token) {
|
||||
case "(", ")", "+", "-", "*", "/": // Valid non-number.
|
||||
xpTail++;
|
||||
return token;
|
||||
default: // Should be number.
|
||||
if (token[0].isDigit()) {
|
||||
while (xpTail < xpr.length && xpr[xpTail].isDigit())
|
||||
xpTail++;
|
||||
return xpr[xpHead .. xpTail];
|
||||
} // Else may be error.
|
||||
} // End switch.
|
||||
}
|
||||
if (xpTail < xpr.length)
|
||||
throw new Exception("Invalid Char <" ~ xpr[xpTail] ~ ">");
|
||||
return null;
|
||||
} // End nextToken.
|
||||
|
||||
AST parse(in string s) {
|
||||
bool expectingOP;
|
||||
xpr = s;
|
||||
try {
|
||||
xpHead = xpTail = 0;
|
||||
num = opr = null;
|
||||
root = null;
|
||||
opr.push(new XP); // CBkt, prevent evaluate null OP precedence.
|
||||
while ((token = nextToken()) !is null) {
|
||||
XP tokenXP = new XP(token, xpHead);
|
||||
if (expectingOP) { // Process OP-alike XP.
|
||||
switch (token) {
|
||||
case ")":
|
||||
while (opr.pop!false().type != Type.OBkt)
|
||||
joinXP(opr.pop());
|
||||
opr.pop();
|
||||
expectingOP = true;
|
||||
break;
|
||||
case "+", "-", "*", "/":
|
||||
while (tokenXP <= opr.pop!false())
|
||||
joinXP(opr.pop());
|
||||
opr.push(tokenXP);
|
||||
expectingOP = false;
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Expecting Operator or ), not <"
|
||||
~ token ~ ">");
|
||||
}
|
||||
} else { // Process Num-alike XP.
|
||||
switch (token) {
|
||||
case "+", "-", "*", "/", ")":
|
||||
throw new Exception("Expecting Number or (, not <"
|
||||
~ token ~ ">");
|
||||
case "(":
|
||||
opr.push(tokenXP);
|
||||
expectingOP = false;
|
||||
break;
|
||||
default: // Number.
|
||||
num.push(tokenXP);
|
||||
expectingOP = true;
|
||||
}
|
||||
}
|
||||
xpHead = xpTail;
|
||||
} // End while.
|
||||
|
||||
while (opr.length > 1) // Join pending Op.
|
||||
joinXP(opr.pop());
|
||||
} catch(Exception e) {
|
||||
writefln("%s\n%s\n%s^", e.msg, xpr, " ".replicate(xpHead));
|
||||
root = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
if (num.length != 1) { // Should be one XP left.
|
||||
writefln("Parse Error...");
|
||||
root = null;
|
||||
} else {
|
||||
root = num.pop();
|
||||
}
|
||||
return this;
|
||||
} // End Parse.
|
||||
} // End class AST.
|
||||
|
||||
// To display AST fancy struct.
|
||||
void ins(ref char[][] s, in string v, in int p, in int l)
|
||||
pure nothrow {
|
||||
if (l + 1 > s.length)
|
||||
s.length++;
|
||||
while (s[l].length < p + v.length + 1)
|
||||
s[l] ~= " ";
|
||||
s[l][p .. p + v.length] = v;
|
||||
}
|
||||
|
||||
final class CalcVis : Visitor {
|
||||
int result, level;
|
||||
string resultStr;
|
||||
char[][] Tree;
|
||||
|
||||
static void opCall(AST a) {
|
||||
if (a && a.root) {
|
||||
auto c = new CalcVis;
|
||||
a.root.accept(c);
|
||||
foreach (immutable i; 1 .. c.Tree.length) { // More fancy.
|
||||
bool flipflop = false;
|
||||
enum char mk = '.';
|
||||
foreach (immutable j; 0 .. c.Tree[i].length) {
|
||||
while (j >= c.Tree[i - 1].length)
|
||||
c.Tree[i - 1] ~= " ";
|
||||
immutable c1 = c.Tree[i][j];
|
||||
immutable c2 = c.Tree[i - 1][j];
|
||||
if (flipflop && (c1 == ' ') && c2 == ' ')
|
||||
c.Tree[i - 1][j] = mk;
|
||||
if (c1 != mk && c1 != ' ' &&
|
||||
(j == 0 || !isDigit(c.Tree[i][j - 1])))
|
||||
flipflop = !flipflop;
|
||||
}
|
||||
}
|
||||
foreach (const t; c.Tree)
|
||||
writefln(t);
|
||||
writefln("\n%s ==>\n%s = %s", a.xpr, c.resultStr, c.result);
|
||||
} else
|
||||
writefln("Evalute invalid or null Expression.");
|
||||
}
|
||||
|
||||
// Calc. the value, display AST struct and eval order.
|
||||
override void visit(XP xp) {
|
||||
ins(Tree, xp.str, xp.pos, level);
|
||||
level++;
|
||||
if (xp.type == Type.Num) {
|
||||
resultStr ~= xp.str;
|
||||
result = to!int(xp.str);
|
||||
} else {
|
||||
resultStr ~= "(";
|
||||
xp.LHS.accept(this);
|
||||
immutable int lhs = result;
|
||||
resultStr ~= opChar[xp.type];
|
||||
xp.RHS.accept(this);
|
||||
resultStr ~= ")";
|
||||
switch (xp.type) {
|
||||
case Type.Add: result = lhs + result; break;
|
||||
case Type.Sub: result = lhs - result; break;
|
||||
case Type.Mul: result = lhs * result; break;
|
||||
case Type.Div: result = lhs / result; break;
|
||||
default: throw new Exception("Invalid type");
|
||||
}
|
||||
}
|
||||
level--;
|
||||
}
|
||||
}
|
||||
|
||||
void main(string[] args) {
|
||||
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;
|
||||
(new AST).parse(exp).CalcVis(); // Should be 60.
|
||||
}
|
||||
18
Task/Arithmetic-evaluation/E/arithmetic-evaluation-1.e
Normal file
18
Task/Arithmetic-evaluation/E/arithmetic-evaluation-1.e
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
def eParser := <elang:syntax.makeEParser>
|
||||
def LiteralExpr := <elang:evm.makeLiteralExpr>.asType()
|
||||
def arithEvaluate(expr :String) {
|
||||
def ast := eParser(expr)
|
||||
|
||||
def evalAST(ast) {
|
||||
return switch (ast) {
|
||||
match e`@a + @b` { evalAST(a) + evalAST(b) }
|
||||
match e`@a - @b` { evalAST(a) - evalAST(b) }
|
||||
match e`@a * @b` { evalAST(a) * evalAST(b) }
|
||||
match e`@a / @b` { evalAST(a) / evalAST(b) }
|
||||
match e`-@a` { -(evalAST(a)) }
|
||||
match l :LiteralExpr { l.getValue() }
|
||||
}
|
||||
}
|
||||
|
||||
return evalAST(ast)
|
||||
}
|
||||
8
Task/Arithmetic-evaluation/E/arithmetic-evaluation-2.e
Normal file
8
Task/Arithmetic-evaluation/E/arithmetic-evaluation-2.e
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
? arithEvaluate("1 + 2")
|
||||
# value: 3
|
||||
|
||||
? arithEvaluate("(1 + 2) * 10 / 100")
|
||||
# value: 0.3
|
||||
|
||||
? arithEvaluate("(1 + 2 / 2) * (5 + 5)")
|
||||
# value: 20.0
|
||||
285
Task/Arithmetic-evaluation/Elena/arithmetic-evaluation-1.elena
Normal file
285
Task/Arithmetic-evaluation/Elena/arithmetic-evaluation-1.elena
Normal file
|
|
@ -0,0 +1,285 @@
|
|||
#define std'dictionary'*.
|
||||
#define std'basic'*.
|
||||
#define std'patterns'*.
|
||||
#define ext'io'*.
|
||||
#define ext'convertors'*.
|
||||
|
||||
#subject parse_order.
|
||||
|
||||
#class Token
|
||||
{
|
||||
#field theValue.
|
||||
|
||||
#initializer
|
||||
[
|
||||
theValue := String.
|
||||
]
|
||||
|
||||
#method parse_order'get = 0.
|
||||
|
||||
#method += aChar
|
||||
[
|
||||
theValue += aChar.
|
||||
]
|
||||
|
||||
#method + aNode
|
||||
[
|
||||
^ aNode += self.
|
||||
]
|
||||
|
||||
#method numeric = Real64Value &&literal:theValue &:erealformatter.
|
||||
}
|
||||
|
||||
|
||||
#class Node
|
||||
{
|
||||
#field theLeft.
|
||||
#field theRight.
|
||||
|
||||
#role LeftAssigned
|
||||
{
|
||||
#method += aNode
|
||||
[
|
||||
theRight := aNode.
|
||||
|
||||
#shift.
|
||||
]
|
||||
}
|
||||
#role Empty
|
||||
{
|
||||
#method += aNode
|
||||
[
|
||||
theLeft := aNode.
|
||||
|
||||
#shift LeftAssigned.
|
||||
]
|
||||
}
|
||||
#initializer
|
||||
[
|
||||
#shift Empty.
|
||||
]
|
||||
|
||||
#method + aNode
|
||||
[
|
||||
#if (self parse_order > aNode parse_order)?
|
||||
[
|
||||
self += aNode.
|
||||
]
|
||||
| [
|
||||
aNode += self.
|
||||
|
||||
^ aNode.
|
||||
].
|
||||
]
|
||||
|
||||
#method += aNode
|
||||
[
|
||||
#if (theRight parse_order > aNode parse_order)?
|
||||
[
|
||||
theRight += aNode.
|
||||
]
|
||||
| [
|
||||
theRight := aNode += theRight.
|
||||
].
|
||||
]
|
||||
}
|
||||
|
||||
#class SummaryNode (Node)
|
||||
{
|
||||
#method parse_order'get = 2.
|
||||
|
||||
#method numeric = theLeft numeric + theRight numeric.
|
||||
}
|
||||
#class DifferenceNode (Node)
|
||||
{
|
||||
#method parse_order'get = 2.
|
||||
|
||||
#method numeric = theLeft numeric - theRight numeric.
|
||||
}
|
||||
#class ProductNode (Node)
|
||||
{
|
||||
#method parse_order'get = 1.
|
||||
|
||||
#method numeric = theLeft numeric * theRight numeric.
|
||||
}
|
||||
#class FractionNode (Node)
|
||||
{
|
||||
#method parse_order'get = 1.
|
||||
|
||||
#method numeric = theLeft numeric / theRight numeric.
|
||||
}
|
||||
#class SubExpression
|
||||
{
|
||||
#field theParser.
|
||||
#field theCounter.
|
||||
|
||||
#role EOF
|
||||
{
|
||||
#method available'is [ control fail. ]
|
||||
|
||||
#method += aChar [ $self fail. ]
|
||||
}
|
||||
|
||||
#initializer
|
||||
[
|
||||
theParser := arithmeval'Parser.
|
||||
theCounter := Integer << 1.
|
||||
]
|
||||
|
||||
#method available'is []
|
||||
|
||||
#method parse_order'get = 0.
|
||||
|
||||
#method + aNode
|
||||
[
|
||||
^ aNode += self.
|
||||
]
|
||||
|
||||
#method append : aChar
|
||||
[
|
||||
#if control if:(aChar == 41)
|
||||
[
|
||||
theCounter -= 1.
|
||||
]
|
||||
| if:(aChar == 40)
|
||||
[
|
||||
theCounter += 1.
|
||||
].
|
||||
|
||||
#if (theCounter == 0)?
|
||||
[ #shift EOF. ^ $self. ].
|
||||
|
||||
theParser evaluate:aChar.
|
||||
]
|
||||
|
||||
#method numeric = theParser numeric.
|
||||
}
|
||||
#class Parser
|
||||
{
|
||||
#field theToken.
|
||||
#field theTopNode.
|
||||
|
||||
#role Brackets
|
||||
{
|
||||
#method evaluate : aChar
|
||||
[
|
||||
theToken += aChar.
|
||||
|
||||
#if theToken available'is
|
||||
| [
|
||||
#shift.
|
||||
].
|
||||
]
|
||||
}
|
||||
#role Start
|
||||
{
|
||||
#method evaluate : aChar
|
||||
[
|
||||
#if (40 == aChar)?
|
||||
[
|
||||
theToken := SubExpression.
|
||||
theTopNode := theToken.
|
||||
|
||||
#shift Brackets.
|
||||
]
|
||||
| [
|
||||
theToken := Token.
|
||||
theTopNode := theToken.
|
||||
|
||||
theToken += aChar.
|
||||
|
||||
#shift.
|
||||
].
|
||||
]
|
||||
}
|
||||
#role Operator
|
||||
{
|
||||
#method evaluate : aChar
|
||||
[
|
||||
#if Control if:(48 < aChar) if:(58 > aChar)
|
||||
[
|
||||
theToken := (Token += aChar).
|
||||
|
||||
theTopNode += theToken.
|
||||
|
||||
#shift.
|
||||
]
|
||||
| if:(40 == aChar)
|
||||
[
|
||||
theToken := SubExpression.
|
||||
theTopNode += theToken.
|
||||
|
||||
#shift Brackets.
|
||||
]
|
||||
| [ $self fail. ].
|
||||
]
|
||||
}
|
||||
|
||||
#initializer
|
||||
[
|
||||
#shift Start.
|
||||
]
|
||||
|
||||
#method numeric = theTopNode numeric.
|
||||
|
||||
#method evaluate : aChar
|
||||
[
|
||||
#if Control if:(48 < aChar) if:(58 > aChar)
|
||||
[
|
||||
theToken += aChar.
|
||||
]
|
||||
| if:(42 == aChar) // *
|
||||
[
|
||||
theTopNode := theTopNode + ProductNode.
|
||||
|
||||
#shift Operator.
|
||||
]
|
||||
| if:(47 == aChar) // /
|
||||
[
|
||||
theTopNode := theTopNode + FractionNode.
|
||||
|
||||
#shift Operator.
|
||||
]
|
||||
| if:(43 == aChar) // +
|
||||
[
|
||||
theTopNode := theTopNode + SummaryNode.
|
||||
|
||||
#shift Operator.
|
||||
]
|
||||
| if:(45 == aChar) // -
|
||||
[
|
||||
theTopNode := theTopNode + DifferenceNode.
|
||||
|
||||
#shift Operator.
|
||||
]
|
||||
| if:(40 == aChar)
|
||||
[
|
||||
theToken := SubExpression.
|
||||
theTopNode := theToken.
|
||||
|
||||
#shift Brackets.
|
||||
]
|
||||
| [ $self fail. ].
|
||||
]
|
||||
|
||||
#method start : aProcess
|
||||
[
|
||||
aProcess run:self.
|
||||
|
||||
^ self numeric.
|
||||
]
|
||||
}
|
||||
|
||||
#symbol Program =
|
||||
[
|
||||
#var aText := String.
|
||||
|
||||
#while ((Console >> aText) length > 0)?
|
||||
[
|
||||
#var aParser := Parser.
|
||||
|
||||
Console << "=" << aParser start:Scan::aText | ^^"Invalid Expression".
|
||||
|
||||
Console << "%n".
|
||||
].
|
||||
].
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
number ::= $numeric;
|
||||
numeric ::= "(" sub_expr;
|
||||
numeric ::= number;
|
||||
factor ::= number factor_r;
|
||||
factor ::= "(" sub_expr;
|
||||
sum ::= "+" factor ;
|
||||
difference ::= "-" factor ;
|
||||
multiply ::= "*" numeric;
|
||||
divide ::= "/" numeric;
|
||||
factor_r ::= multiply factor_r;
|
||||
factor_r ::= divide factor_r;
|
||||
factor_r ::= $eps;
|
||||
expr_r ::= sum expr_r;
|
||||
expr_r ::= difference expr_r;
|
||||
expr_r ::= $eps;
|
||||
neg_r ::= factor_r expr_r;
|
||||
sub_expr ::= expression sub_expr_r;
|
||||
sub_expr_r ::= ")" factor_r;
|
||||
neg_expression ::= $numeric neg_r;
|
||||
expression ::= factor expr_r;
|
||||
expression ::= "-" neg_expression;
|
||||
print ::= "?" expression;
|
||||
start ::= print;
|
||||
print => &nil 'program'output $body ^write;
|
||||
multiply => $body ^multiply;
|
||||
divide => $body ^divide;
|
||||
sum => $body ^add;
|
||||
difference => $body ^subtract;
|
||||
neg_expression => 0 $terminal ^subtract $body;
|
||||
number => $terminal $body;
|
||||
Loading…
Add table
Add a link
Reference in a new issue