RosettaCodeData/Task/Arithmetic-evaluation/Elena/arithmetic-evaluation.elena

344 lines
6.2 KiB
Text
Raw Permalink Normal View History

2019-09-12 10:33:56 -07:00
import system'routines;
import extensions;
import extensions'text;
2015-11-18 06:14:39 +00:00
2017-09-23 10:01:46 +02:00
class Token
2015-11-18 06:14:39 +00:00
{
2019-09-12 10:33:56 -07:00
object theValue;
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
rprop int Level;
2017-09-23 10:01:46 +02:00
2019-09-12 10:33:56 -07:00
constructor new(int level)
{
theValue := new StringWriter();
Level := level + 9;
}
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
append(ch)
{
theValue.write(ch)
}
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
Number = theValue.toReal();
2015-11-18 06:14:39 +00:00
}
2017-09-23 10:01:46 +02:00
class Node
2015-11-18 06:14:39 +00:00
{
2019-09-12 10:33:56 -07:00
prop object Left;
prop object Right;
rprop int Level;
constructor new(int level)
{
Level := level
}
2015-11-18 06:14:39 +00:00
}
2019-09-12 10:33:56 -07:00
class SummaryNode : Node
2015-11-18 06:14:39 +00:00
{
2019-09-12 10:33:56 -07:00
constructor new(int level)
<= new(level + 1);
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
Number = Left.Number + Right.Number;
2015-11-18 06:14:39 +00:00
}
2019-09-12 10:33:56 -07:00
class DifferenceNode : Node
2015-11-18 06:14:39 +00:00
{
2019-09-12 10:33:56 -07:00
constructor new(int level)
<= new(level + 1);
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
Number = Left.Number - Right.Number;
2015-11-18 06:14:39 +00:00
}
2019-09-12 10:33:56 -07:00
class ProductNode : Node
2015-11-18 06:14:39 +00:00
{
2019-09-12 10:33:56 -07:00
constructor new(int level)
<= new(level + 2);
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
Number = Left.Number * Right.Number;
2015-11-18 06:14:39 +00:00
}
2019-09-12 10:33:56 -07:00
class FractionNode : Node
2015-11-18 06:14:39 +00:00
{
2019-09-12 10:33:56 -07:00
constructor new(int level)
<= new(level + 2);
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
Number = Left.Number / Right.Number;
2015-11-18 06:14:39 +00:00
}
2017-09-23 10:01:46 +02:00
class Expression
2015-11-18 06:14:39 +00:00
{
2019-09-12 10:33:56 -07:00
rprop int Level;
prop object Top;
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
constructor new(int level)
{
Level := level
}
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
prop object Right
{
get() = Top;
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
set(object node)
{
Top := node
}
}
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
get Number() => Top;
2015-11-18 06:14:39 +00:00
}
2018-08-17 15:15:24 +01:00
singleton operatorState
{
eval(ch)
2019-09-12 10:33:56 -07:00
{
2018-08-17 15:15:24 +01:00
ch =>
2019-09-12 10:33:56 -07:00
$40 { // (
^ __target.newBracket().gotoStarting()
}
: {
^ __target.newToken().append(ch).gotoToken()
}
}
2018-08-17 15:15:24 +01:00
}
2015-11-18 06:14:39 +00:00
2018-08-17 15:15:24 +01:00
singleton tokenState
{
eval(ch)
2019-09-12 10:33:56 -07:00
{
2018-08-17 15:15:24 +01:00
ch =>
2019-09-12 10:33:56 -07:00
$41 { // )
^ __target.closeBracket().gotoToken()
}
$42 { // *
^ __target.newProduct().gotoOperator()
}
$43 { // +
^ __target.newSummary().gotoOperator()
}
$45 { // -
^ __target.newDifference().gotoOperator()
}
$47 { // /
^ __target.newFraction().gotoOperator()
}
: {
^ __target.append:ch
}
}
2018-08-17 15:15:24 +01:00
}
2015-11-18 06:14:39 +00:00
2018-08-17 15:15:24 +01:00
singleton startState
{
eval(ch)
2019-09-12 10:33:56 -07:00
{
2018-08-17 15:15:24 +01:00
ch =>
2019-09-12 10:33:56 -07:00
$40 { // (
^ __target.newBracket().gotoStarting()
}
$45 { // -
^ __target.newToken().append("0").newDifference().gotoOperator()
}
: {
^ __target.newToken().append:ch.gotoToken()
}
}
2018-08-17 15:15:24 +01:00
}
2015-11-18 06:14:39 +00:00
2017-09-23 10:01:46 +02:00
class Scope
2015-11-18 06:14:39 +00:00
{
2019-09-12 10:33:56 -07:00
object theState;
int theLevel;
object theParser;
object theToken;
object theExpression;
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
constructor new(parser)
{
theState := startState;
theLevel := 0;
theExpression := Expression.new(0);
theParser := parser
}
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
newToken()
{
theToken := theParser.appendToken(theExpression, theLevel)
}
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
newSummary()
{
theToken := nil;
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
theParser.appendSummary(theExpression, theLevel)
}
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
newDifference()
{
theToken := nil;
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
theParser.appendDifference(theExpression, theLevel)
}
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
newProduct()
{
theToken := nil;
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
theParser.appendProduct(theExpression, theLevel)
}
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
newFraction()
{
theToken := nil;
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
theParser.appendFraction(theExpression, theLevel)
}
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
newBracket()
{
theToken := nil;
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
theLevel := theLevel + 10;
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
theParser.appendSubexpression(theExpression, theLevel)
}
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
closeBracket()
{
2017-09-23 10:01:46 +02:00
if (theLevel < 10)
2019-09-12 10:33:56 -07:00
{ InvalidArgumentException.new:"Invalid expression".raise() };
2015-11-18 06:14:39 +00:00
2017-09-23 10:01:46 +02:00
theLevel := theLevel - 10
2019-09-12 10:33:56 -07:00
}
append(ch)
{
if(ch >= $48 && ch < $58)
{
theToken.append:ch
}
else
{
InvalidArgumentException.new:"Invalid expression".raise()
}
}
append(string s)
{
s.forEach:(ch){ self.append:ch }
}
gotoStarting()
{
2017-09-23 10:01:46 +02:00
theState := startState
2019-09-12 10:33:56 -07:00
}
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
gotoToken()
{
2017-09-23 10:01:46 +02:00
theState := tokenState
2019-09-12 10:33:56 -07:00
}
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
gotoOperator()
{
2017-09-23 10:01:46 +02:00
theState := operatorState
2019-09-12 10:33:56 -07:00
}
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
get Number() => theExpression;
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
dispatch() => theState;
2015-11-18 06:14:39 +00:00
}
2017-09-23 10:01:46 +02:00
class Parser
2015-11-18 06:14:39 +00:00
{
2019-09-12 10:33:56 -07:00
appendToken(object expression, int level)
{
var token := Token.new(level);
expression.Top := self.append(expression.Top, token);
^ token
}
appendSummary(object expression, int level)
{
expression.Top := self.append(expression.Top, SummaryNode.new(level))
}
appendDifference(object expression, int level)
{
expression.Top := self.append(expression.Top, DifferenceNode.new(level))
}
appendProduct(object expression, int level)
{
expression.Top := self.append(expression.Top, ProductNode.new(level))
}
appendFraction(object expression, int level)
{
expression.Top := self.append(expression.Top, FractionNode.new(level))
}
appendSubexpression(object expression, int level)
{
expression.Top := self.append(expression.Top, Expression.new(level))
}
append(object lastNode, object newNode)
{
if(nil == lastNode)
{ ^ newNode };
if (newNode.Level <= lastNode.Level)
{ newNode.Left := lastNode; ^ newNode };
var parent := lastNode;
var current := lastNode.Right;
while (nil != current && newNode.Level > current.Level)
{ parent := current; current := current.Right };
if (nil == current)
{
parent.Right := newNode
}
else
{
newNode.Left := current; parent.Right := newNode
};
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
^ lastNode
}
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
run(text)
{
var scope := Scope.new(self);
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
text.forEach:(ch){ scope.eval:ch };
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
^ scope.Number
}
}
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
public program()
{
var text := new StringWriter();
var parser := new Parser();
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
while (console.readLine().saveTo(text).Length > 0)
{
try
{
console.printLine("=",parser.run:text)
}
catch(Exception e)
{
console.writeLine(e.Printable)
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
//console.writeLine:"Invalid Expression"
};
2015-11-18 06:14:39 +00:00
2019-09-12 10:33:56 -07:00
text.clear()
}
2015-11-18 06:14:39 +00:00
}