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

344 lines
5.7 KiB
Text
Raw Permalink Normal View History

2023-07-01 11:58:00 -04:00
import system'routines;
import extensions;
import extensions'text;
class Token
{
2023-09-01 09:35:06 -07:00
object _value;
2023-07-01 11:58:00 -04:00
2023-09-01 09:35:06 -07:00
int Level : rprop;
2023-07-01 11:58:00 -04:00
2023-09-01 09:35:06 -07:00
constructor new(int level)
{
_value := new StringWriter();
Level := level + 9;
}
2023-07-01 11:58:00 -04:00
2023-09-01 09:35:06 -07:00
append(ch)
{
_value.write(ch)
}
2023-07-01 11:58:00 -04:00
2023-09-01 09:35:06 -07:00
Number = _value.toReal();
2023-07-01 11:58:00 -04:00
}
class Node
{
2023-09-01 09:35:06 -07:00
object Left : prop;
object Right : prop;
int Level : rprop;
constructor new(int level)
{
Level := level
}
2023-07-01 11:58:00 -04:00
}
class SummaryNode : Node
{
2023-09-01 09:35:06 -07:00
constructor new(int level)
<= super new(level + 1);
2023-07-01 11:58:00 -04:00
2023-09-01 09:35:06 -07:00
Number = Left.Number + Right.Number;
2023-07-01 11:58:00 -04:00
}
class DifferenceNode : Node
{
2023-09-01 09:35:06 -07:00
constructor new(int level)
<= super new(level + 1);
2023-07-01 11:58:00 -04:00
2023-09-01 09:35:06 -07:00
Number = Left.Number - Right.Number;
2023-07-01 11:58:00 -04:00
}
class ProductNode : Node
{
2023-09-01 09:35:06 -07:00
constructor new(int level)
<= super new(level + 2);
2023-07-01 11:58:00 -04:00
2023-09-01 09:35:06 -07:00
Number = Left.Number * Right.Number;
2023-07-01 11:58:00 -04:00
}
class FractionNode : Node
{
2023-09-01 09:35:06 -07:00
constructor new(int level)
<= super new(level + 2);
2023-07-01 11:58:00 -04:00
2023-09-01 09:35:06 -07:00
Number = Left.Number / Right.Number;
2023-07-01 11:58:00 -04:00
}
class Expression
{
2023-09-01 09:35:06 -07:00
int Level :rprop;
object Top :prop;
2023-07-01 11:58:00 -04:00
2023-09-01 09:35:06 -07:00
constructor new(int level)
{
Level := level
}
2023-07-01 11:58:00 -04:00
2023-09-01 09:35:06 -07:00
object Right
{
get() = Top;
2023-07-01 11:58:00 -04:00
2023-09-01 09:35:06 -07:00
set(object node)
{
Top := node
}
}
2023-07-01 11:58:00 -04:00
2023-09-01 09:35:06 -07:00
get Number() => Top;
2023-07-01 11:58:00 -04:00
}
singleton operatorState
{
2023-09-01 09:35:06 -07:00
eval(ch)
{
ch =>
2025-08-11 18:05:26 -07:00
$40 : { // (
2023-09-01 09:35:06 -07:00
^ weak self.newBracket().gotoStarting()
}
2025-08-11 18:05:26 -07:00
! : {
2023-09-01 09:35:06 -07:00
^ weak self.newToken().append(ch).gotoToken()
}
}
2023-07-01 11:58:00 -04:00
}
singleton tokenState
{
2023-09-01 09:35:06 -07:00
eval(ch)
{
ch =>
2025-08-11 18:05:26 -07:00
$41 : { // )
2023-09-01 09:35:06 -07:00
^ weak self.closeBracket().gotoToken()
}
2025-08-11 18:05:26 -07:00
$42 : { // *
2023-09-01 09:35:06 -07:00
^ weak self.newProduct().gotoOperator()
}
2025-08-11 18:05:26 -07:00
$43 : { // +
2023-09-01 09:35:06 -07:00
^ weak self.newSummary().gotoOperator()
}
2025-08-11 18:05:26 -07:00
$45 : { // -
2023-09-01 09:35:06 -07:00
^ weak self.newDifference().gotoOperator()
}
2025-08-11 18:05:26 -07:00
$47 : { // /
2023-09-01 09:35:06 -07:00
^ weak self.newFraction().gotoOperator()
}
2025-08-11 18:05:26 -07:00
! : {
2024-03-06 22:25:12 -08:00
^ weak self.append(ch)
2023-09-01 09:35:06 -07:00
}
}
2023-07-01 11:58:00 -04:00
}
singleton startState
{
2023-09-01 09:35:06 -07:00
eval(ch)
{
ch =>
2025-08-11 18:05:26 -07:00
$40 : { // (
2023-09-01 09:35:06 -07:00
^ weak self.newBracket().gotoStarting()
}
2025-08-11 18:05:26 -07:00
$45 : { // -
2023-09-01 09:35:06 -07:00
^ weak self.newToken().append("0").newDifference().gotoOperator()
}
2025-08-11 18:05:26 -07:00
! : {
2024-03-06 22:25:12 -08:00
^ weak self.newToken().append(ch).gotoToken()
2023-09-01 09:35:06 -07:00
}
}
2023-07-01 11:58:00 -04:00
}
class Scope
{
2025-08-11 18:05:26 -07:00
object _state;
int _level;
object _parser;
object? _token;
object _expression;
2023-09-01 09:35:06 -07:00
constructor new(parser)
{
_state := startState;
_level := 0;
_expression := Expression.new(0);
_parser := parser
}
newToken()
{
_token := _parser.appendToken(_expression, _level)
}
newSummary()
{
_token := nil;
_parser.appendSummary(_expression, _level)
}
newDifference()
{
_token := nil;
_parser.appendDifference(_expression, _level)
}
newProduct()
{
_token := nil;
_parser.appendProduct(_expression, _level)
}
newFraction()
{
_token := nil;
_parser.appendFraction(_expression, _level)
}
newBracket()
{
_token := nil;
_level := _level + 10;
_parser.appendSubexpression(_expression, _level)
}
closeBracket()
{
if (_level < 10)
2024-03-06 22:25:12 -08:00
{ InvalidArgumentException.new("Invalid expression").raise() };
2023-09-01 09:35:06 -07:00
_level := _level - 10
}
append(ch)
{
if(ch >= $48 && ch < $58)
{
2024-03-06 22:25:12 -08:00
_token.append(ch)
2023-09-01 09:35:06 -07:00
}
else
{
2024-03-06 22:25:12 -08:00
InvalidArgumentException.new("Invalid expression").raise()
2023-09-01 09:35:06 -07:00
}
}
append(string s)
{
2024-03-06 22:25:12 -08:00
s.forEach::(ch){ self.append(ch) }
2023-09-01 09:35:06 -07:00
}
gotoStarting()
{
_state := startState
}
gotoToken()
{
_state := tokenState
}
gotoOperator()
{
_state := operatorState
}
get Number() => _expression;
dispatch() => _state;
2023-07-01 11:58:00 -04:00
}
class Parser
{
2023-09-01 09:35:06 -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)
{
var t := expression.Top;
expression.Top := self.append(/*expression.Top*/t, 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
};
^ lastNode
}
run(text)
{
var scope := Scope.new(self);
2024-03-06 22:25:12 -08:00
text.forEach::(ch){ scope.eval(ch) };
2023-09-01 09:35:06 -07:00
^ scope.Number
}
2023-07-01 11:58:00 -04:00
}
2026-02-01 16:33:20 -08:00
public Program()
2023-07-01 11:58:00 -04:00
{
2023-09-01 09:35:06 -07:00
var text := new StringWriter();
var parser := new Parser();
2025-08-11 18:05:26 -07:00
while (Console.readLine().writeTo(text).Length > 0)
2023-09-01 09:35:06 -07:00
{
try
{
2026-02-01 16:33:20 -08:00
Console.printLine("=",parser.run(text as:string))
2023-09-01 09:35:06 -07:00
}
catch(Exception e)
{
2025-08-11 18:05:26 -07:00
Console.writeLine("Invalid Expression")
2023-09-01 09:35:06 -07:00
};
text.clear()
}
2023-07-01 11:58:00 -04:00
}