Arithmetic evaluation: Difference between revisions

m (Liberty BASIC added)
Line 1,057:
 
=={{header|Elena}}==
<lang elena>#define std'dictionary'*system.
#define std'basic'*extensions.
#define std'patterns'*.
#define ext'io'*.
#define ext'convertors'*.
 
#subject parse_order.
 
#class Token
Line 1,069 ⟶ 1,064:
#field theValue.
#initializerconstructor new
[
theValue := String new.
]
#constructor new : aValue
#method parse_order'get = 0.
[
theValue := String new:aValue.
]
#method +ParseOrder = aChar0.
#method append : aChar
[
theValue += aChar.
]
#method +add : aNode
[
^ aNode += self.
]
 
#method numericNumber = Real64ValueconvertControl &&literaltoReal:theValue &:erealformatter.
}
 
#class(role) ENoneAssigned
{
#method append : anObject
=> %setLeft.
}
 
#class(role) ELeftAssigned
{
#method append : anObject
=> %setRight.
}
 
#class(role) ERightAssigned
{
#method append : anObject
=> %appendRight.
}
 
#class Node
Line 1,094 ⟶ 1,111:
#field theLeft.
#field theRight.
#field theState.
#rolemethod LeftAssignedsetRight : aNode
{
#method += aNode
[
theRight := aNode.
#shift.
]
}
#role Empty
{
#method += aNode
[
theLeft := aNode.
#shift LeftAssigned.
]
}
#initializer
[
#shifttheRight Empty:= aNode.
theState := ERightAssigned.
]
 
#method +setLeft : aNode
[
#iftheLeft (self parse_order >:= aNode parse_order)?.
[
theState self +:= aNodeELeftAssigned.
]
| [
aNode += self.
^ aNode.
].
]
#constructor new
[
theState := ENoneAssigned.
]
 
#method add : aNode
= (self ParseOrder > aNode ParseOrder)
? [
self += aNode.
^ self.
]
! [
aNode += self.
^ aNode.
].
#method +=appendRight : aNode
[
#if (theRight parse_orderParseOrder > aNode parse_orderParseOrder)?
? [
theRight += aNode.
]
|! [
theRight := aNode += theRight.
].
]
#method => theState.
}
 
#class SummaryNode (: Node)
{
#method parse_order'getParseOrder = 2.
#method numericNumber = theLeft numericNumber + theRight numericNumber.
}
 
#class DifferenceNode (Node)
#class DifferenceNode : Node
{
#method parse_order'getParseOrder = 2.
#method numericNumber = theLeft numericNumber - theRight numericNumber.
}
 
#class ProductNode (Node)
#class ProductNode : Node
{
#method parse_order'getParseOrder = 1.
#method numericNumber = theLeft numericNumber * theRight numericNumber.
}
 
#class FractionNode (Node)
#class FractionNode : Node
{
#method parse_order'getParseOrder = 1.
#method numericNumber = theLeft numericNumber / theRight numericNumber.
}
 
#class SubExpression
{
Line 1,172 ⟶ 1,192:
#field theCounter.
#roleconstructor EOFnew
{
#method available'is [ control fail. ]
#method += aChar [ $self fail. ]
}
#initializer
[
theParser := arithmeval'Parser new.
theCounter := Integer << new:1.
]
 
#method ParseOrder = 0.
#method available'isadd []: aNode
#method parse_order'get = 0.
#method + aNode
[
^ aNode += self.
]
#method append : aCharvalidate
[
#if control if:(aChartheCounter ==< 410)
? [ #throw Exception new:"Invalid expression". ].
[
theCounter -= 1.
]^ (0 == theCounter).
| if:(aChar == 40)
[
theCounter += 1.
].
#if (theCounter == 0)?
[ #shift EOF. ^ $self. ].
theParser evaluate:aChar.
]
#method numericappend =: theParser numeric.aChar
[
aChar =>
41 ? [
theCounter -= 1.
]
40 ? [ theCounter += 1 ]
! [ theParser evaluate:aChar ].
]
 
#method Number
= $self validate
? [ theParser Number ]
! [ #throw Exception new:"Invalid expression". ].
}
 
#class Parser
#class(role)EStartState
{
#method eval : aChar
=> %onStart.
}
 
#class(role)EBracketState
{
#method eval : aChar
=> %onBrackets.
}
 
#class(role)EOperatorState
{
#method eval : aChar
=> %onOperator.
}
 
#class(role)ENumberState
{
#method eval : aChar
=> %onDigit.
}
 
#class Parser : system'routines'BasePattern
{
#field theToken.
#field theTopNode.
#field theRole.
#method onBrackets : aChar
#role Brackets
{[
#methodtheToken evaluate :+= aChar.
[
(theToken += aChar.validate)
? [
#if theToken available'istheRole := ENumberState.
| [].
]
#shift.
 
].
#method onStart : ]aChar
} [
#role Start aChar =>
40 ? [ // (
{
#method evaluate theToken := SubExpression aCharnew.
[
#if (40 == aChar)?
[
theToken := SubExpression.
theTopNode := theToken.
theRole := EBracketState.
]
45 ? [ // -
theToken := DifferenceNode new add:(Token new:"0").
#shifttheTopNode Brackets:= theToken.
theRole := EOperatorState.
]
|! [
theToken := Token new.
theTopNode := theToken.
theRole := ENumberState.
theToken +=$self appendDigit:aChar.
#shift.
].
]
 
}
#method onOperator : aChar
#role Operator
{[
#methodaChar evaluate : aChar=>
40 ? [
#if Control if:(48 < aChar)theToken if:(58= >SubExpression aChar)new.
[
theToken := (Token += aChar).
theTopNode += theToken.
theRole := EBracketState.
#shift.
]
|! if:(40 == aChar)[
[ theToken := Token new.
theToken := SubExpression.
theTopNode += theToken.
theRole := ENumberState.
 
#shift Brackets.
] $self appendDigit:aChar.
| [ $self fail. ].
]
 
}
#constructor new
#initializer
[
#shifttheRole Start:= EStartState.
]
 
#method numericNumber = theTopNode numericNumber.
 
#method evaluateappendDigit : aChar
[
#if(aChar Control>= if:(48 < aChar) ifand:(58aChar >< aChar58)
? [
theToken += aChar.
]
|! if:(42 == aChar) // *[
#throw Exception new:"Invalid expression".
[
theTopNode := theTopNode + ProductNode.
#shift Operator.
]
| if:(47 == aChar) // /
[
theTopNode := theTopNode + FractionNode.
#shift Operator.
]
| if:(43 == aChar) // +
[
theTopNode := theTopNode + SummaryNode.
#shift Operator.
]
| if:(45 == aChar) // -
[
theTopNode := theTopNode + DifferenceNode.
#shift Operator.
]
| if:(40 == aChar)
[
theToken := SubExpression.
theTopNode := theToken.
#shift Brackets.
]
| [ $self fail. ].
]
 
#method startonDigit : aProcessaChar
[
aProcessaChar run:self.=>
40 ? [ // (
^ self numeric theToken := SubExpression new.
theTopNode := theToken.
theRole := EBracketState.
]
42 ? [ // *
theTopNode := theTopNode + ProductNode new.
 
theRole := EOperatorState.
]
43 ? [ // +
theTopNode := theTopNode + SummaryNode new.
 
theRole := EOperatorState.
]
45 ? [ // -
theTopNode := theTopNode + DifferenceNode new.
 
theRole := EOperatorState.
]
47 ? // /
[
theTopNode := theTopNode + FractionNode new.
 
theRole := EOperatorState.
]
! [
$self appendDigit:aChar.
].
]
 
#method => theRole.
}
 
#symbol Programprogram =
[
#var aText := String new.
 
#control while :((Console >>consoleEx readLine:aText) lengthLength > 0)? &do:
[
#var aParser := Parser new.
 
Console <<consoleEx writeLine:"=" << :(aParser start:Scan:foreach:aText | ^^"Invalid Expression".Number)
| ifFailed:
Console << "%n". [
consoleEx writeLine:"Invalid Expression".
].
].
].</lang>
</lang>
 
=== ELENA VM script ===
Anonymous user