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. |
|||
] |
] |
||
# |
#method level = theLevel. |
||
[ |
|||
theValue := String new:aValue. |
|||
] |
|||
#method |
#method append &char:aChar |
||
#method append : aChar |
|||
[ |
[ |
||
theValue += aChar. |
theValue += aChar. |
||
] |
] |
||
#method |
#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 |
#field theLevel. |
||
#method setRight : aNode |
|||
[ |
|||
theRight := aNode. |
|||
theState := %appendRight. |
|||
] |
|||
#method setLeft : aNode |
|||
[ |
|||
theLeft := aNode. |
|||
theState := %setRight. |
|||
] |
|||
#constructor new |
|||
[ |
|||
theState := %setLeft. |
|||
] |
|||
# |
#constructor new &level:aLevel |
||
= (self ParseOrder > aNode ParseOrder) |
|||
? [ |
|||
self += aNode. |
|||
^ self. |
|||
] |
|||
! [ |
|||
aNode += self. |
|||
^ aNode. |
|||
]. |
|||
#method appendRight : aNode |
|||
[ |
[ |
||
theLevel := aLevel. |
|||
? [ |
|||
theRight += aNode. |
|||
] |
|||
! [ |
|||
theRight := aNode += theRight. |
|||
]. |
|||
] |
] |
||
#method |
#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. ] |
|||
} |
} |
||
#class SummaryNode :: Node |
|||
#class SummaryNode : Node |
|||
{ |
{ |
||
#constructor new &level:aLevel |
|||
#method ParseOrder = 2. |
|||
<= %new &level:(aLevel + 1). |
|||
#method |
#method number = theLeft number + theRight number. |
||
} |
} |
||
#class DifferenceNode :: Node |
|||
#class DifferenceNode : Node |
|||
{ |
{ |
||
#constructor new &level:aLevel |
|||
#method ParseOrder = 2. |
|||
<= %new &level:(aLevel + 1). |
|||
#method |
#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 |
#method number = theLeft number * theRight number. |
||
} |
} |
||
#class FractionNode :: Node |
|||
{ |
|||
#constructor new &level:aLevel |
|||
<= %new &level:(aLevel + 2). |
|||
#method number = theLeft number / theRight number. |
|||
} |
|||
#class |
#class Expression |
||
{ |
{ |
||
# |
#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 |
#field theToken. |
||
#field theExpression. |
|||
#constructor new |
#constructor new &parser:aParser |
||
[ |
[ |
||
theState := startState. |
|||
theLevel := 0. |
|||
theExpression := Expression new &level:0. |
|||
theParser := aParser. |
|||
] |
] |
||
#method |
#method new &token |
||
[ |
|||
theToken := theParser append &token &expression:theExpression &level:theLevel. |
|||
] |
|||
#method |
#method new &summary |
||
[ |
[ |
||
theToken := nil. |
|||
theParser append &summary &expression:theExpression &level:theLevel. |
|||
] |
|||
#method |
#method new &difference |
||
[ |
[ |
||
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 |
#method goto &start |
||
[ |
[ |
||
theState := startState. |
|||
41 ? [ |
|||
theCounter -= 1. |
|||
] |
|||
40 ? [ theCounter += 1 ] |
|||
! [ theParser evaluate:aChar ]. |
|||
] |
] |
||
#method |
#method goto &token |
||
[ |
|||
= $self validate |
|||
theState := tokenState. |
|||
] |
|||
! [ #throw Exception new:"Invalid expression". ]. |
|||
#method goto &operator |
|||
[ |
|||
theState := operatorState. |
|||
] |
|||
#method number => theExpression. |
|||
#method => theState. |
|||
} |
} |
||
#class Parser |
|||
#class Parser : system'routines'BasePattern |
|||
{ |
{ |
||
#method append &token &expression:anExpression &level:aLevel |
|||
#field theToken. |
|||
#field theTopNode. |
|||
#field theState. |
|||
#method onBrackets : aChar |
|||
[ |
[ |
||
#var aToken := Token new &level:aLevel. |
|||
anExpression set &top:($self append &last:(anExpression top) &new:aToken). |
|||
(theToken validate) |
|||
^ aToken. |
|||
]. |
|||
] |
] |
||
#method |
#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 |
#method append &difference &expression:anExpression &level:aLevel |
||
[ |
[ |
||
anExpression set &top:($self append &last:(anExpression top) &new:(DifferenceNode new &level:aLevel)). |
|||
aChar => |
|||
] |
|||
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 |
#method append &subexpression &expression:anExpression &level:aLevel |
||
[ |
|||
anExpression set &top:($self append &last:(anExpression top) &new:(Expression new &level:aLevel)). |
|||
] |
|||
#method |
#method append &last:aLastNode &new:aNewNode |
||
[ |
[ |
||
( |
(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 |
#method run : aText |
||
[ |
[ |
||
#var aScope := Scope new &parser:$self. |
|||
40 ? [ // ( |
|||
theToken := SubExpression new. |
|||
theTopNode := theToken. |
|||
theState := %onBrackets. |
|||
] |
|||
42 ? [ // * |
|||
theTopNode := theTopNode + ProductNode new. |
|||
control run:aText &forEach: ch [ aScope eval:ch. ]. |
|||
] |
|||
43 ? [ // + |
|||
theTopNode := theTopNode + SummaryNode new. |
|||
^ 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: |
control while:[ consoleEx readLine:aText length > 0] &do: |
||
[ |
[ |
||
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}}== |