Arithmetic evaluation: Difference between revisions

m
(Added FutureBasic solution)
Line 1,313:
 
=={{header|Elena}}==
ELENA 56.0x :
<syntaxhighlight lang="elena">import/// a program which parses and evaluates arithmetic expressions. system'routines;
 
import system'routines;
import extensions;
import extensions'text;
 
// --- Token ---
 
class Token
{
object theValue_value;
rprop int Level : rprop;
constructor new(int level)
{
theValue_value := new StringWriter();
Level := level + 9;
}
append(ch)
{
theValue_value.write(ch)
}
Number = theValue_value.toReal();
}
 
// --- Node ---
 
class Node
{
prop object Left : prop;
prop object Right : prop;
rprop int Level : rprop;
 
constructor new(int level)
{
Level := level
}
}
 
// --- SummaryNode
 
class SummaryNode : Node
{
constructor new(int level)
<= super new(level + 1);
Number = Left.Number + Right.Number;
}
 
// --- DifferenceNode ---
 
class DifferenceNode : Node
{
constructor new(int level)
<= super new(level + 1);
Number = Left.Number - Right.Number;
}
 
// --- ProductNode ---
 
class ProductNode : Node
{
constructor new(int level)
<= super new(level + 2);
Number = Left.Number * Right.Number;
}
 
// --- FractionNode ---
 
class FractionNode : Node
{
constructor new(int level)
<= super new(level + 2);
Number = Left.Number / Right.Number;
}
 
// --- Expression ---
 
class Expression
{
rprop int Level :rprop;
prop object Top :prop;
constructor new(int level)
{
Level := level
}
object Right
{
get() = Top;
set(object node)
{
Top := node
}
}
get Number() => Top;
}
 
// --- States ---
 
singleton operatorState
{
eval(ch)
{
ch =>
$40 { // (
^ weak ^ __targetself.newBracket().gotoStarting()
}
: {
^ weak ^ __targetself.newToken().append(ch).gotoToken()
}
}
}
 
singleton tokenState
{
eval(ch)
{
ch =>
$41 { // )
^ weak ^ __targetself.closeBracket().gotoToken()
}
$42 { // *
^ weak ^ __targetself.newProduct().gotoOperator()
}
$43 { // +
^ weak ^ __targetself.newSummary().gotoOperator()
}
$45 { // -
^ weak ^ __targetself.newDifference().gotoOperator()
}
$47 { // /
^ weak ^ __targetself.newFraction().gotoOperator()
}
: {
^ weak ^ __targetself.append:ch
}
}
}
 
singleton startState
{
eval(ch)
{
ch =>
$40 { // (
^ weak ^ __targetself.newBracket().gotoStarting()
}
$45 { // -
^ weak ^ __targetself.newToken().append("0").newDifference().gotoOperator()
}
: {
^ weak ^ __targetself.newToken().append:ch.gotoToken()
}
}
}
 
// --- Scope ---
 
class Scope
{
object theState_state;
int theLevel_level;
object theParser_parser;
object theToken_token;
object theExpression_expression;
constructor new(parser)
{
theState_state := startState;
theLevel_level := 0;
theExpression_expression := Expression.new(0);
theParser_parser := parser
}
newToken()
{
theToken_token := theParser_parser.appendToken(theExpression_expression, theLevel_level)
}
newSummary()
{
theToken_token := nil;
theParser_parser.appendSummary(theExpression_expression, theLevel_level)
}
newDifference()
{
theToken_token := nil;
theParser_parser.appendDifference(theExpression_expression, theLevel_level)
}
newProduct()
{
theToken_token := nil;
theParser_parser.appendProduct(theExpression_expression, theLevel_level)
}
newFraction()
{
theToken_token := nil;
theParser_parser.appendFraction(theExpression_expression, theLevel_level)
}
 
newBracket()
{
theToken_token := nil;
theLevel_level := theLevel_level + 10;
theParser_parser.appendSubexpression(theExpression_expression, theLevel_level)
}
 
closeBracket()
{
if (theLevel_level < 10)
{ InvalidArgumentException.new:"Invalid expression".raise() };
theLevel_level := theLevel_level - 10
}
append(ch)
{
if(ch >= $48 && ch < $58)
{
theToken_token.append:ch
}
else
{
InvalidArgumentException.new:"Invalid expression".raise()
}
}
append(string s)
{
s.forEach:(ch){ self.append:ch }
}
gotoStarting()
{
theState_state := startState
}
gotoToken()
{
theState_state := tokenState
}
gotoOperator()
{
theState_state := operatorState
}
get Number() => theExpression_expression;
dispatch() => theState_state;
}
 
// ---- Parser ----
 
class Parser
{
appendToken(object expression, int level)
{
var token := Token.new(level);
expression.Top := self.append(expression.Top, token);
^ token
}
 
appendSummary(object expression, int level)
{
var expression.Topt := self.append(expression.Top, SummaryNode.new(level));
 
}
expression.Top := self.append(/*expression.Top*/t, SummaryNode.new(level))
}
appendDifference(object expression, int level)
 
{
appendDifference(object expression.Top, :=int self.append(expression.Top, DifferenceNode.new(level))
}{
expression.Top := self.append(expression.Top, DifferenceNode.new(level))
}
appendProduct(object expression, int level)
 
{
appendProduct(object expression.Top, :=int self.append(expression.Top, ProductNode.new(level))
}{
expression.Top := self.append(expression.Top, ProductNode.new(level))
}
appendFraction(object expression, int level)
 
{
appendFraction(object expression.Top, :=int self.append(expression.Top, FractionNode.new(level))
}{
expression.Top := self.append(expression.Top, FractionNode.new(level))
}
appendSubexpression(object expression, int level)
 
{
appendSubexpression(object expression.Top, :=int self.append(expression.Top, Expression.new(level))
}{
expression.Top := self.append(expression.Top, Expression.new(level))
}
append(lastNode, newNode)
 
{
append(object lastNode, object newNode)
if(nil == lastNode)
{
{ ^ newNode };
if(nil == lastNode)
if (newNode.Level{ <=^ newNode lastNode.Level)};
{ newNode.Left := lastNode; ^ newNode };
if (newNode.Level <= lastNode.Level)
var parent{ newNode.Left := lastNode; ^ newNode };
var current := lastNode.Right;
var parent := lastNode;
while (nil != current && newNode.Level > current.Level)
{ parent := current;var current := currentlastNode.Right };
while (nil != current && newNode.Level > current.Level)
if (nil{ parent := current; current := current).Right };
{
if (nil parent.Right :== newNode current)
{ }
else parent.Right := newNode
{ }
else
newNode.Left := current; parent.Right := newNode
{ };
newNode.Left := current; parent.Right := newNode
^ lastNode};
}
^ lastNode
run(text)}
{
run(text)
var scope := Scope.new(self);
{
var scope text:= Scope.forEach:new(chself){ scope.eval:ch };
 
^text.forEach:(ch){ scope.Numbereval:ch };
 
}
^ scope.Number
}
}
 
public program()
{
var text := new StringWriter();
var parser := new Parser();
 
while (console.readLine().saveTowriteTo(text).Length > 0)
{
try
{
console.printLine("=",parser.run:text)
}
catch(Exception e)
{
console.writeLine:"Invalid Expression"(e.toPrintable())
};
//console.writeLine:"Invalid Expression"
text.clear()};
}
text.clear()
}
}</syntaxhighlight>
 
11

edits