Arithmetic evaluation: Difference between revisions

Content added Content deleted
Line 1,061: Line 1,061:
<lang elena>#define system.
<lang elena>#define system.
#define extensions.
#define extensions.

// --- Token ---


#class Token
#class Token
{
{
#field theValue.
#field theValue.
#field theLevel.
#constructor new
#constructor new &level:aLevel
[
[
theValue := String new.
theValue := String new.
theLevel := aLevel + 9.
]
]
#constructor new : aValue
#method level = theLevel.
[
theValue := String new:aValue.
]
#method ParseOrder = 0.
#method append &char:aChar
#method append : aChar
[
[
theValue += aChar.
theValue += aChar.
]
]
#method add : aNode
#method number = convertor toReal:(theValue value).
[
^ aNode += self.
]

#method Number = convertor toReal:(theValue value).
}
}

// --- Node ---


#class Node
#class Node
Line 1,099: Line 1,087:
#field theLeft.
#field theLeft.
#field theRight.
#field theRight.
#field theState.
#field theLevel.
#method setRight : aNode
[
theRight := aNode.
theState := %appendRight.
]
#method setLeft : aNode
[
theLeft := aNode.
theState := %setRight.
]
#constructor new
[
theState := %setLeft.
]


#method add : aNode
#constructor new &level:aLevel
= (self ParseOrder > aNode ParseOrder)
? [
self += aNode.
^ self.
]
! [
aNode += self.
^ aNode.
].
#method appendRight : aNode
[
[
(theRight ParseOrder > aNode ParseOrder)
theLevel := aLevel.
? [
theRight += aNode.
]
! [
theRight := aNode += theRight.
].
]
]
#method append : anObject
#method level = theLevel.

= $self~theState eval:anObject.
#method left = theLeft.

#method => theState.
#method right = theRight.

#method set &left:anObject [ theLeft := anObject. ]

#method set &right:anObject [ theRight := anObject. ]
}
}


// --- SummaryNode
#class SummaryNode :: Node

#class SummaryNode : Node
{
{
#constructor new &level:aLevel
#method ParseOrder = 2.
<= %new &level:(aLevel + 1).
#method Number = theLeft Number + theRight Number.
#method number = theLeft number + theRight number.
}
}


// --- DifferenceNode ---
#class DifferenceNode :: Node

#class DifferenceNode : Node
{
{
#constructor new &level:aLevel
#method ParseOrder = 2.
<= %new &level:(aLevel + 1).
#method Number = theLeft Number - theRight Number.
#method number = theLeft number - theRight number.
}
}


// --- ProductNode ---
// --- ProductNode ---


#class ProductNode : Node
#class ProductNode :: Node
{
{
#constructor new &level:aLevel
#method ParseOrder = 1.
<= %new &level:(aLevel + 2).
#method Number = theLeft Number * theRight Number.
#method number = theLeft number * theRight number.
}
}


// --- FractionNode ---
#class FractionNode :: Node
{
#constructor new &level:aLevel
<= %new &level:(aLevel + 2).
#method number = theLeft number / theRight number.
}


#class FractionNode : Node
#class Expression
{
{
#method ParseOrder = 1.
#field theLevel.
#field theTop.
#constructor new &level:aLevel
#method Number = theLeft Number / theRight Number.
[
theLevel := aLevel.
]
#method top = theTop.

#method set &top:aNode [ theTop := aNode. ]
#method right = theTop.

#method set &right:aNode [ theTop := aNode. ]
#method level = theLevel.
#method number => theTop.
}
}


#symbol operatorState = (:ch)
// --- SubExpression ---
[
ch =>
#40 ? [ // (
self new &bracket goto &start.
]
! [
self new &token append &char:ch goto &token.
].
].


#symbol tokenState = (:ch)
#class SubExpression
[
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 &char:ch.
].
].

#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 &char:ch goto &token.
].
].

#class Scope
{
{
#field theState.
#field theLevel.
#field theParser.
#field theParser.
#field theCounter.
#field theToken.
#field theExpression.
#constructor new
#constructor new &parser:aParser
[
[
theParser := arithmeval'Parser new.
theState := startState.
theCounter := Integer new:1.
theLevel := 0.
theExpression := Expression new &level:0.
theParser := aParser.
]
]

#method ParseOrder = 0.
#method new &token
[
theToken := theParser append &token &expression:theExpression &level:theLevel.
]
#method add : aNode
#method new &summary
[
[
^ aNode += self.
theToken := nil.
]
theParser append &summary &expression:theExpression &level:theLevel.
]
#method validate
#method new &difference
[
[
(theCounter < 0)
theToken := nil.
? [ #throw Exception new:"Invalid expression". ].
theParser append &difference &expression:theExpression &level:theLevel.
]
#method new &product
[
theToken := nil.
theParser append &product &expression:theExpression &level:theLevel.
]
#method new &fraction
[
theToken := nil.
theParser append &fraction &expression:theExpression &level:theLevel.
]

#method new &bracket
[
theToken := nil.
theLevel := theLevel + 10.
theParser append &subexpression &expression:theExpression &level:theLevel.
]

#method close &bracket
[
(theLevel < 10)
? [ #throw InvalidArgumentException new &message:"Invalid expression". ].
theLevel := theLevel - 10.
]
#method append &char:ch
[
((ch >= 48) and:(ch < 58))
? [ theToken append &char:ch. ]
! [ #throw InvalidArgumentException new &message:"Invalid expression". ].
]
#method append &literal:aLiteral
^ (0 == theCounter).
[
control run:aLiteral &forEach: ch [ self append &char:ch. ].
]
]
#method append : aChar
#method goto &start
[
[
aChar =>
theState := startState.
41 ? [
theCounter -= 1.
]
40 ? [ theCounter += 1 ]
! [ theParser evaluate:aChar ].
]
]

#method Number
#method goto &token
[
= $self validate
? [ theParser Number ]
theState := tokenState.
]
! [ #throw Exception new:"Invalid expression". ].
#method goto &operator
[
theState := operatorState.
]
#method number => theExpression.
#method => theState.
}
}


// ---- Parser ----
#class Parser

#class Parser : system'routines'BasePattern
{
{
#method append &token &expression:anExpression &level:aLevel
#field theToken.
#field theTopNode.
#field theState.
#method onBrackets : aChar
[
[
theToken += aChar.
#var aToken := Token new &level:aLevel.
anExpression set &top:($self append &last:(anExpression top) &new:aToken).
(theToken validate)
? [
theState := %onDigit.
^ aToken.
].
]
]


#method onStart : aChar
#method append &summary &expression:anExpression &level:aLevel
[
[
anExpression set &top:($self append &last:(anExpression top) &new:(SummaryNode new &level:aLevel)).
aChar =>
40 ? [ // (
theToken := SubExpression new.
theTopNode := theToken.
theState := %onBrackets.
]
45 ? [ // -
theToken := DifferenceNode new add:(Token new:"0").
theTopNode := theToken.
theState := %onOperator.
]
! [
theToken := Token new.
theTopNode := theToken.
theState := %onDigit.
$self appendDigit:aChar.
].
]
]


#method onOperator : aChar
#method append &difference &expression:anExpression &level:aLevel
[
[
anExpression set &top:($self append &last:(anExpression top) &new:(DifferenceNode new &level:aLevel)).
aChar =>
40 ? [
]
theToken := SubExpression new.
theTopNode += theToken.
theState := %onBrackets.
]
! [
theToken := Token new.
theTopNode += theToken.
theState := %onDigit.


#method append &product &expression:anExpression &level:aLevel
$self appendDigit:aChar.
].
[
anExpression set &top:($self append &last:(anExpression top) &new:(ProductNode new &level:aLevel)).
]
]


#method append &fraction &expression:anExpression &level:aLevel
#constructor new
[
[
anExpression set &top:($self append &last:(anExpression top) &new:(FractionNode new &level:aLevel)).
theState := %onStart.
]
]


#method Number = theTopNode Number.
#method append &subexpression &expression:anExpression &level:aLevel
[
anExpression set &top:($self append &last:(anExpression top) &new:(Expression new &level:aLevel)).
]


#method appendDigit : aChar
#method append &last:aLastNode &new:aNewNode
[
[
(aChar >= 48) and:(aChar < 58)
(nil == aLastNode)
? [
? [ ^ aNewNode. ].
theToken += aChar.
]
! [
#throw Exception new:"Invalid expression".
]
(aNewNode level <= aLastNode level)
? [ aNewNode set &left:aLastNode. ^ aNewNode. ].
#var aParent := aLastNode.
#var aCurrent := aLastNode right.
#loop ((aCurrent != nil) and:[ aNewNode level > aCurrent level ]) ?
[ aParent := aCurrent. aCurrent := aCurrent right. ].
(nil == aCurrent)
? [ aParent set &right:aNewNode. ]
! [ aNewNode set &left:aCurrent. aParent set &right:aNewNode. ].
^ aLastNode.
]
]

#method onDigit : aChar
#method run : aText
[
[
aChar =>
#var aScope := Scope new &parser:$self.
40 ? [ // (
theToken := SubExpression new.
theTopNode := theToken.
theState := %onBrackets.
]
42 ? [ // *
theTopNode := theTopNode + ProductNode new.


theState := %onOperator.
control run:aText &forEach: ch [ aScope eval:ch. ].
]
43 ? [ // +
theTopNode := theTopNode + SummaryNode new.


theState := %onOperator.
^ aScope number.
]
45 ? [ // -
theTopNode := theTopNode + DifferenceNode new.

theState := %onOperator.
]
47 ? // /
[
theTopNode := theTopNode + FractionNode new.

theState := %onOperator.
]
! [
$self appendDigit:aChar.
].
]
]

#method eval : aChar = $self~theState eval:aChar.
}
}


Line 1,349: Line 1,378:
[
[
#var aText := String new.
#var aText := String new.
#var aParser := Parser new.


control while:(consoleEx readLine:aText length > 0) &do:
control while:[ consoleEx readLine:aText length > 0] &do:
[
[
#var aParser := Parser new.
consoleEx writeLine:"=" :(aParser run:aText)
| if &Error:e [

consoleEx writeLine:"=" :(aParser foreach:aText Number)
| if &e:
[
consoleEx writeLine:"Invalid Expression".
consoleEx writeLine:"Invalid Expression".
].
].
].
].
].</lang>
].</lang>

=== ELENA VM script ===
<lang elena>number ::= $numeric;
numeric ::= "(" sub_expr;
numeric ::= number;
factor ::= number factor_r;
factor ::= "(" sub_expr;
sum ::= "+" factor ;
difference ::= "-" factor ;
multiply ::= "*" numeric;
divide ::= "/" numeric;
factor_r ::= multiply factor_r;
factor_r ::= divide factor_r;
factor_r ::= $eps;
expr_r ::= sum expr_r;
expr_r ::= difference expr_r;
expr_r ::= $eps;
neg_r ::= factor_r expr_r;
sub_expr ::= expression sub_expr_r;
sub_expr_r ::= ")" factor_r;
neg_expression ::= $numeric neg_r;
expression ::= factor expr_r;
expression ::= "-" neg_expression;
print ::= "?" expression;
start ::= print;
print => &nil 'program'output $body ^write;
multiply => $body ^multiply;
divide => $body ^divide;
sum => $body ^add;
difference => $body ^subtract;
neg_expression => 0 $terminal ^subtract $body;
number => $terminal $body;</lang>


=={{header|ERRE}}==
=={{header|ERRE}}==