Arithmetic evaluation: Difference between revisions
Content added Content deleted
Alextretyak (talk | contribs) m (→{{header|11l}}) |
|||
Line 1,183: | Line 1,183: | ||
=={{header|Elena}}== |
=={{header|Elena}}== |
||
ELENA |
ELENA 4.x : |
||
<lang elena>import system'routines |
<lang elena>import system'routines; |
||
import extensions |
import extensions; |
||
import extensions'text |
import extensions'text; |
||
class Token |
class Token |
||
{ |
{ |
||
object theValue |
object theValue; |
||
rprop int Level; |
|||
constructor new(int |
constructor new(int level) |
||
{ |
|||
theValue := |
theValue := new StringWriter(); |
||
Level := level + 9; |
|||
} |
|||
append |
append(ch) |
||
{ |
|||
theValue |
theValue.write(ch) |
||
} |
|||
Number = theValue.toReal(); |
|||
} |
} |
||
class Node |
class Node |
||
{ |
{ |
||
prop object Left; |
|||
prop object Right; |
|||
rprop int Level; |
|||
constructor new(int |
constructor new(int level) |
||
{ |
|||
Level := level |
|||
} |
|||
} |
} |
||
class SummaryNode |
class SummaryNode : Node |
||
{ |
{ |
||
constructor new(int |
constructor new(int level) |
||
<= new( |
<= new(level + 1); |
||
Number = Left.Number + Right.Number; |
|||
} |
} |
||
class DifferenceNode |
class DifferenceNode : Node |
||
{ |
{ |
||
constructor new(int |
constructor new(int level) |
||
<= new( |
<= new(level + 1); |
||
Number = Left.Number - Right.Number; |
|||
} |
} |
||
class ProductNode |
class ProductNode : Node |
||
{ |
{ |
||
constructor new(int |
constructor new(int level) |
||
<= new( |
<= new(level + 2); |
||
Number = Left.Number * Right.Number; |
|||
} |
} |
||
class FractionNode |
class FractionNode : Node |
||
{ |
{ |
||
constructor new(int |
constructor new(int level) |
||
<= new( |
<= new(level + 2); |
||
Number = Left.Number / Right.Number; |
|||
} |
} |
||
class Expression |
class Expression |
||
{ |
{ |
||
rprop int Level; |
|||
prop object Top; |
|||
constructor new(int |
constructor new(int level) |
||
{ |
|||
Level := level |
|||
} |
|||
prop object Right |
|||
{ |
|||
get() = Top; |
|||
⚫ | |||
set(object node) |
|||
{ |
|||
Top := node |
|||
} |
|||
} |
|||
get Number() => Top; |
|||
} |
} |
||
Line 1,272: | Line 1,278: | ||
{ |
{ |
||
eval(ch) |
eval(ch) |
||
{ |
|||
ch => |
ch => |
||
$40 |
$40 { // ( |
||
^ |
^ __target.newBracket().gotoStarting() |
||
} |
|||
: { |
|||
^ |
^ __target.newToken().append(ch).gotoToken() |
||
} |
|||
} |
|||
} |
} |
||
Line 1,286: | Line 1,292: | ||
{ |
{ |
||
eval(ch) |
eval(ch) |
||
{ |
|||
ch => |
ch => |
||
$41 |
$41 { // ) |
||
^ |
^ __target.closeBracket().gotoToken() |
||
} |
|||
$42 |
$42 { // * |
||
^ |
^ __target.newProduct().gotoOperator() |
||
} |
|||
$43 |
$43 { // + |
||
^ |
^ __target.newSummary().gotoOperator() |
||
} |
|||
$45 |
$45 { // - |
||
^ |
^ __target.newDifference().gotoOperator() |
||
} |
|||
$47 |
$47 { // / |
||
^ |
^ __target.newFraction().gotoOperator() |
||
} |
|||
: { |
|||
^ |
^ __target.append:ch |
||
} |
|||
} |
|||
} |
} |
||
Line 1,312: | Line 1,318: | ||
{ |
{ |
||
eval(ch) |
eval(ch) |
||
{ |
|||
ch => |
ch => |
||
$40 |
$40 { // ( |
||
^ |
^ __target.newBracket().gotoStarting() |
||
} |
|||
$45 |
$45 { // - |
||
^ |
^ __target.newToken().append("0").newDifference().gotoOperator() |
||
} |
|||
: { |
|||
^ |
^ __target.newToken().append:ch.gotoToken() |
||
} |
|||
} |
|||
} |
} |
||
class Scope |
class Scope |
||
{ |
{ |
||
object theState |
object theState; |
||
int theLevel |
int theLevel; |
||
object theParser |
object theParser; |
||
object theToken |
object theToken; |
||
object theExpression |
object theExpression; |
||
constructor new |
constructor new(parser) |
||
{ |
|||
theState := startState |
theState := startState; |
||
theLevel := 0 |
theLevel := 0; |
||
theExpression := Expression |
theExpression := Expression.new(0); |
||
theParser := |
theParser := parser |
||
} |
|||
newToken |
newToken() |
||
{ |
|||
theToken := theParser |
theToken := theParser.appendToken(theExpression, theLevel) |
||
} |
|||
newSummary |
newSummary() |
||
{ |
|||
theToken := nil |
theToken := nil; |
||
theParser |
theParser.appendSummary(theExpression, theLevel) |
||
} |
|||
newDifference |
newDifference() |
||
{ |
|||
theToken := nil |
theToken := nil; |
||
theParser |
theParser.appendDifference(theExpression, theLevel) |
||
} |
|||
newProduct |
newProduct() |
||
{ |
|||
theToken := nil |
theToken := nil; |
||
theParser |
theParser.appendProduct(theExpression, theLevel) |
||
} |
|||
newFraction |
newFraction() |
||
{ |
|||
theToken := nil |
theToken := nil; |
||
theParser |
theParser.appendFraction(theExpression, theLevel) |
||
} |
|||
newBracket |
newBracket() |
||
{ |
|||
theToken := nil |
theToken := nil; |
||
theLevel := theLevel + 10 |
theLevel := theLevel + 10; |
||
theParser |
theParser.appendSubexpression(theExpression, theLevel) |
||
} |
|||
closeBracket |
closeBracket() |
||
{ |
|||
if (theLevel < 10) |
if (theLevel < 10) |
||
{ InvalidArgumentException.new:"Invalid expression".raise() }; |
|||
theLevel := theLevel - 10 |
theLevel := theLevel - 10 |
||
} |
|||
append |
append(ch) |
||
{ |
|||
if |
if(ch >= $48 && ch < $58) |
||
{ |
|||
theToken.append:ch |
|||
⚫ | |||
} |
|||
else |
|||
{ |
|||
⚫ | |||
} |
|||
} |
|||
append( |
append(string s) |
||
{ |
|||
s.forEach:(ch){ self.append:ch } |
|||
} |
|||
gotoStarting |
gotoStarting() |
||
{ |
|||
theState := startState |
theState := startState |
||
} |
|||
gotoToken |
gotoToken() |
||
{ |
|||
theState := tokenState |
theState := tokenState |
||
} |
|||
gotoOperator |
gotoOperator() |
||
{ |
|||
theState := operatorState |
theState := operatorState |
||
} |
|||
get Number() => theExpression; |
|||
dispatch => theState |
dispatch() => theState; |
||
} |
} |
||
class Parser |
class Parser |
||
{ |
{ |
||
appendToken(object |
appendToken(object expression, int level) |
||
{ |
|||
var |
var token := Token.new(level); |
||
expression.Top := self.append(expression.Top, token); |
|||
^ |
^ token |
||
} |
|||
appendSummary(object |
appendSummary(object expression, int level) |
||
{ |
|||
expression.Top := self.append(expression.Top, SummaryNode.new(level)) |
|||
} |
|||
appendDifference(object |
appendDifference(object expression, int level) |
||
{ |
|||
expression.Top := self.append(expression.Top, DifferenceNode.new(level)) |
|||
} |
|||
appendProduct(object |
appendProduct(object expression, int level) |
||
{ |
|||
expression.Top := self.append(expression.Top, ProductNode.new(level)) |
|||
} |
|||
appendFraction(object |
appendFraction(object expression, int level) |
||
{ |
|||
expression.Top := self.append(expression.Top, FractionNode.new(level)) |
|||
} |
|||
appendSubexpression(object |
appendSubexpression(object expression, int level) |
||
{ |
|||
expression.Top := self.append(expression.Top, Expression.new(level)) |
|||
} |
|||
append(object |
append(object lastNode, object newNode) |
||
{ |
|||
if(nil == |
if(nil == lastNode) |
||
{ ^ newNode }; |
|||
if ( |
if (newNode.Level <= lastNode.Level) |
||
{ newNode.Left := lastNode; ^ newNode }; |
|||
var |
var parent := lastNode; |
||
var |
var current := lastNode.Right; |
||
while |
while (nil != current && newNode.Level > current.Level) |
||
{ parent := current; current := current.Right }; |
|||
if (nil == |
if (nil == current) |
||
{ |
|||
parent.Right := newNode |
|||
} |
|||
else |
|||
{ |
|||
newNode.Left := current; parent.Right := newNode |
|||
}; |
|||
^ |
^ lastNode |
||
} |
|||
run |
run(text) |
||
{ |
|||
var |
var scope := Scope.new(self); |
||
text.forEach:(ch){ scope.eval:ch }; |
|||
^ |
^ scope.Number |
||
} |
|||
} |
} |
||
public program |
public program() |
||
{ |
|||
[ |
|||
var |
var text := new StringWriter(); |
||
var |
var parser := new Parser(); |
||
while (console.readLine().saveTo(text).Length > 0) |
|||
{ |
|||
try |
try |
||
{ |
{ |
||
console.printLine("=",parser.run:text) |
|||
} |
|||
catch(Exception e) |
|||
⚫ | |||
{ |
|||
console.writeLine(e.Printable) |
|||
⚫ | |||
⚫ | |||
}; |
|||
⚫ | |||
text.clear() |
|||
} |
|||
⚫ | |||
=={{header|Emacs Lisp}}== |
=={{header|Emacs Lisp}}== |