Arithmetic evaluation: Difference between revisions

(added Scheme example)
Line 1,061:
 
=={{header|Elena}}==
ELENA 3.x :
<lang elena>#import system.
<lang elena>#import system'routines.
#import extensions.
#import extensions'text.
 
#class Token
{
#fieldobject theValue.
#fieldobject outprop(level) theLevel.
#constructor new &level:aLevel
[
theValue := StringWriter new.
Line 1,077:
]
#methodappend level: = theLevel.aChar
#method append : aChar
[
theValue << aChar.
]
#method number = theValue get toReal.
}
 
#class Node
{
#fieldobject prop(left) theLeft.
#fieldobject prop(right) theRight.
#fieldobject outprop(level) theLevel.
 
#constructor new &level:aLevel
[
theLevel := aLevel.
]
#method level = theLevel.
 
#method left = theLeft.
 
#method right = theRight.
 
#method set &left:anObject [ theLeft := anObject. ]
 
#method set &right:anObject [ theRight := anObject. ]
}
 
#class SummaryNode :: Node
{
#constructor new &level:aLevel
<= %new &level:(aLevel + 1).
#method number = theLeft number + theRight number.
}
 
#class DifferenceNode :: Node
{
#constructor new &level:aLevel
<= %new &level:(aLevel + 1).
#method number = theLeft number - theRight number.
}
 
#class ProductNode :: Node
{
#constructor new &level:aLevel
<= %new &level:(aLevel + 2).
#method number = theLeft number * theRight number.
}
 
#class FractionNode :: Node
{
#constructor new &level:aLevel
<= %new &level:(aLevel + 2).
#method number = theLeft number / theRight number.
}
 
#class Expression
{
#fieldobject outprop(level) theLevel.
#fieldobject prop(top) theTop.
#constructor new &level:aLevel
[
theLevel := aLevel.
]
#method topright = theTop.
 
#method set &topright:aNode [ theTop := aNode. ]
#method right = theTop.
 
#method set &right:aNode [ theTop := aNode. ]
#method level = theLevel.
#method number => theTop.
}
 
#symbol operatorState = (:ch)
[
ch =>
#40 ? [ // (
self new &bracket goto &start.
];
! [
self new &token append:ch goto &token.
].
].
 
#symbol tokenState = (:ch)
[
ch =>
#41 ? [ // )
self close &bracket goto &token.
];
#42 ? [ // *
self new &product goto &operator.
];
#43 ? [ // +
self new &summary goto &operator.
];
#45 ? [ // -
self new &difference goto &operator.
];
#47 ? [ // /
[
self new &fraction goto &operator.
];
! [
self append:ch.
Line 1,199 ⟶ 1,180:
].
 
#symbol startState = (:ch)
[
ch =>
#40 ? [ // (
self new &bracket goto &start.
];
#45 ? [ // -
self new &token append &literal:"0" new &difference goto &operator.
];
! [
self new &token append:ch goto &token.
Line 1,213 ⟶ 1,194:
].
 
#class Scope
{
#fieldobject theState.
#fieldobject theLevel.
#fieldobject theParser.
#fieldobject theToken.
#fieldobject theExpression.
#constructor new &parser:aParser
[
theState := startState.
Line 1,229 ⟶ 1,210:
]
#method new &token
[
theToken := theParser append &tokenappendToken &expression:theExpression &level:theLevel.
]
#method new &summary
[
theToken := nil.
theParser append &summaryappendSummary &expression:theExpression &level:theLevel.
]
#method new &difference
[
theToken := nil.
theParser append &differenceappendDifference &expression:theExpression &level:theLevel.
]
#method new &product
[
theToken := nil.
theParser append &productappendProduct &expression:theExpression &level:theLevel.
]
#method new &fraction
[
theToken := nil.
theParser append &fractionappendFraction &expression:theExpression &level:theLevel.
]
 
#method new &bracket
[
theToken := nil.
Line 1,268 ⟶ 1,249:
theLevel := theLevel + 10.
theParser append &subexpressionappendSubexpression &expression:theExpression &level:theLevel.
]
 
#method close &bracket
[
if (theLevel < 10)
? [ #throw InvalidArgumentException new &message:"Invalid expression" raise. ].
theLevel := theLevel - 10.
]
#method append:ch
[
if((ch >= #48) and:&& (ch < #58))
? [ theToken append:ch. ];
! [ #throw InvalidArgumentException new &message:"Invalid expression" raise. ].
]
#method append &literal:aLiteral
[
aLiteral run &each: ch [ self append:ch. ].
]
#method goto &start
[
theState := startState.
]
#method goto &token
[
theState := tokenState.
]
#method goto &operator
[
theState := operatorState.
]
#method number => theExpression.
#methoddispatch => theState.
}
 
#class Parser
{
#method append &tokenappendToken &expression:anExpression &level:aLevel
[
#var aToken := Token new &level:aLevel.
anExpression set &top:($self append &last:(anExpression top) &new:aToken).
Line 1,322 ⟶ 1,303:
]
 
#method append &summaryappendSummary &expression:anExpression &level:aLevel
[
anExpression set &top:($self append &last:(anExpression top) &new:(SummaryNode new &level:aLevel)).
]
 
#method append &differenceappendDifference &expression:anExpression &level:aLevel
[
anExpression set &top:($self append &last:(anExpression top) &new:(DifferenceNode new &level:aLevel)).
]
 
#method append &productappendProduct &expression:anExpression &level:aLevel
[
anExpression set &top:($self append &last:(anExpression top) &new:(ProductNode new &level:aLevel)).
]
 
#method append &fractionappendFraction &expression:anExpression &level:aLevel
[
anExpression set &top:($self append &last:(anExpression top) &new:(FractionNode new &level:aLevel)).
]
 
#method append &subexpressionappendSubexpression &expression:anExpression &level:aLevel
[
anExpression set &top:($self append &last:(anExpression top) &new:(Expression new &level:aLevel)).
]
 
#method append &last:aLastNode &new:aNewNode
[
($nil == aLastNode)
? [ ^ aNewNode. ].
if (aNewNode level <= aLastNode level)
? [ aNewNode set &left:aLastNode. ^ aNewNode. ].
#var aParent := aLastNode.
#var aCurrent := aLastNode right.
#loopwhile (($nil != aCurrent) and:&& [ aNewNode level > aCurrent level ]) ?
[ aParent := aCurrent. aCurrent := aCurrent right. ].
if ($nil == aCurrent)
? [ aParent set &right:aNewNode. ];
! [ aNewNode set &left:aCurrent. aParent set &right:aNewNode. ].
^ aLastNode.
]
#method run : aText
[
#var aScope := Scope new &parser:$self.
 
aText run &each: ch [ aScope eval:ch. ].
Line 1,377 ⟶ 1,358:
}
 
#symbol program =
[
#var aText := String new.
#var aParser := Parser new.
 
[ console readLine save &to:aText length > 0] doWhile:
[
try(console writeLine:"=" :(aParser run:aText))
| if &Error:e [{
! e console writeLine:"Invalid Expression".[
]console writeLine:"Invalid Expression".
]
}.
aText clear.
Anonymous user