344 lines
6.2 KiB
Plaintext
344 lines
6.2 KiB
Plaintext
import system'routines;
|
|
import extensions;
|
|
import extensions'text;
|
|
|
|
class Token
|
|
{
|
|
object theValue;
|
|
|
|
rprop int Level;
|
|
|
|
constructor new(int level)
|
|
{
|
|
theValue := new StringWriter();
|
|
Level := level + 9;
|
|
}
|
|
|
|
append(ch)
|
|
{
|
|
theValue.write(ch)
|
|
}
|
|
|
|
Number = theValue.toReal();
|
|
}
|
|
|
|
class Node
|
|
{
|
|
prop object Left;
|
|
prop object Right;
|
|
rprop int Level;
|
|
|
|
constructor new(int level)
|
|
{
|
|
Level := level
|
|
}
|
|
}
|
|
|
|
class SummaryNode : Node
|
|
{
|
|
constructor new(int level)
|
|
<= new(level + 1);
|
|
|
|
Number = Left.Number + Right.Number;
|
|
}
|
|
|
|
class DifferenceNode : Node
|
|
{
|
|
constructor new(int level)
|
|
<= new(level + 1);
|
|
|
|
Number = Left.Number - Right.Number;
|
|
}
|
|
|
|
class ProductNode : Node
|
|
{
|
|
constructor new(int level)
|
|
<= new(level + 2);
|
|
|
|
Number = Left.Number * Right.Number;
|
|
}
|
|
|
|
class FractionNode : Node
|
|
{
|
|
constructor new(int level)
|
|
<= new(level + 2);
|
|
|
|
Number = Left.Number / Right.Number;
|
|
}
|
|
|
|
class Expression
|
|
{
|
|
rprop int Level;
|
|
prop object Top;
|
|
|
|
constructor new(int level)
|
|
{
|
|
Level := level
|
|
}
|
|
|
|
prop object Right
|
|
{
|
|
get() = Top;
|
|
|
|
set(object node)
|
|
{
|
|
Top := node
|
|
}
|
|
}
|
|
|
|
get Number() => Top;
|
|
}
|
|
|
|
singleton operatorState
|
|
{
|
|
eval(ch)
|
|
{
|
|
ch =>
|
|
$40 { // (
|
|
^ __target.newBracket().gotoStarting()
|
|
}
|
|
: {
|
|
^ __target.newToken().append(ch).gotoToken()
|
|
}
|
|
}
|
|
}
|
|
|
|
singleton tokenState
|
|
{
|
|
eval(ch)
|
|
{
|
|
ch =>
|
|
$41 { // )
|
|
^ __target.closeBracket().gotoToken()
|
|
}
|
|
$42 { // *
|
|
^ __target.newProduct().gotoOperator()
|
|
}
|
|
$43 { // +
|
|
^ __target.newSummary().gotoOperator()
|
|
}
|
|
$45 { // -
|
|
^ __target.newDifference().gotoOperator()
|
|
}
|
|
$47 { // /
|
|
^ __target.newFraction().gotoOperator()
|
|
}
|
|
: {
|
|
^ __target.append:ch
|
|
}
|
|
}
|
|
}
|
|
|
|
singleton startState
|
|
{
|
|
eval(ch)
|
|
{
|
|
ch =>
|
|
$40 { // (
|
|
^ __target.newBracket().gotoStarting()
|
|
}
|
|
$45 { // -
|
|
^ __target.newToken().append("0").newDifference().gotoOperator()
|
|
}
|
|
: {
|
|
^ __target.newToken().append:ch.gotoToken()
|
|
}
|
|
}
|
|
}
|
|
|
|
class Scope
|
|
{
|
|
object theState;
|
|
int theLevel;
|
|
object theParser;
|
|
object theToken;
|
|
object theExpression;
|
|
|
|
constructor new(parser)
|
|
{
|
|
theState := startState;
|
|
theLevel := 0;
|
|
theExpression := Expression.new(0);
|
|
theParser := parser
|
|
}
|
|
|
|
newToken()
|
|
{
|
|
theToken := theParser.appendToken(theExpression, theLevel)
|
|
}
|
|
|
|
newSummary()
|
|
{
|
|
theToken := nil;
|
|
|
|
theParser.appendSummary(theExpression, theLevel)
|
|
}
|
|
|
|
newDifference()
|
|
{
|
|
theToken := nil;
|
|
|
|
theParser.appendDifference(theExpression, theLevel)
|
|
}
|
|
|
|
newProduct()
|
|
{
|
|
theToken := nil;
|
|
|
|
theParser.appendProduct(theExpression, theLevel)
|
|
}
|
|
|
|
newFraction()
|
|
{
|
|
theToken := nil;
|
|
|
|
theParser.appendFraction(theExpression, theLevel)
|
|
}
|
|
|
|
newBracket()
|
|
{
|
|
theToken := nil;
|
|
|
|
theLevel := theLevel + 10;
|
|
|
|
theParser.appendSubexpression(theExpression, theLevel)
|
|
}
|
|
|
|
closeBracket()
|
|
{
|
|
if (theLevel < 10)
|
|
{ InvalidArgumentException.new:"Invalid expression".raise() };
|
|
|
|
theLevel := theLevel - 10
|
|
}
|
|
|
|
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()
|
|
{
|
|
theState := startState
|
|
}
|
|
|
|
gotoToken()
|
|
{
|
|
theState := tokenState
|
|
}
|
|
|
|
gotoOperator()
|
|
{
|
|
theState := operatorState
|
|
}
|
|
|
|
get Number() => theExpression;
|
|
|
|
dispatch() => theState;
|
|
}
|
|
|
|
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)
|
|
{
|
|
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
|
|
};
|
|
|
|
^ lastNode
|
|
}
|
|
|
|
run(text)
|
|
{
|
|
var scope := Scope.new(self);
|
|
|
|
text.forEach:(ch){ scope.eval:ch };
|
|
|
|
^ scope.Number
|
|
}
|
|
}
|
|
|
|
public program()
|
|
{
|
|
var text := new StringWriter();
|
|
var parser := new Parser();
|
|
|
|
while (console.readLine().saveTo(text).Length > 0)
|
|
{
|
|
try
|
|
{
|
|
console.printLine("=",parser.run:text)
|
|
}
|
|
catch(Exception e)
|
|
{
|
|
console.writeLine(e.Printable)
|
|
|
|
//console.writeLine:"Invalid Expression"
|
|
};
|
|
|
|
text.clear()
|
|
}
|
|
}
|