Arithmetic evaluation: Difference between revisions

jq
(Added Nim implementation)
(jq)
Line 3,002:
evalArithmeticExp('2 * (3 + (4 * 5 + (6 * 7) * 8) - 9) * 10') // 7000
evalArithmeticExp('2*-3--4+-0.25' // -2.25</pre>
 
=={{header|jq}}==
 
This entry highlights the use of a PEG grammar expressed in jq.
 
=== PEG operations ===
<lang jq>def star(E): (E | star(E)) // .;
def plus(E): E | (plus(E) // . );
def optional(E): E // .;
def amp(E): . as $in | E | $in;
def neg(E): select( [E] == [] );</lang>
 
 
=== Helper functions ===
<lang jq>def literal($s):
select(.remainder | startswith($s))
| .result += [$s]
| .remainder |= .[$s | length :] ;
 
def box(E):
((.result = null) | E) as $e
| .remainder = $e.remainder
| .result += [$e.result] # the magic sauce
;
 
# Consume a regular expression rooted at the start of .remainder, or emit empty;
# on success, update .remainder and set .match but do NOT update .result
def consume($re):
# on failure, match yields empty
(.remainder | match("^" + $re)) as $match
| .remainder |= .[$match.length :]
| .match = $match.string ;
 
def parseNumber($re):
consume($re)
| .result = .result + [.match|tonumber] ;</lang>
 
=== PEG Grammar ===
The PEG grammar for arithmetic expressions follows the one given at the Perl 6 entry.<lang jq>def Expr:
 
def ws: consume(" *");
 
def Number: ws | parseNumber( "-?[0-9]+([.][0-9]*)?" );
def Sum:
def Parenthesized: ws | consume("[(]") | ws | box(Sum) | ws | consume("[)]");
def Factor: Parenthesized // Number;
def Product: box(Factor | star( ws | (literal("*") // literal("/")) | Factor));
Product | ws | star( (literal("+") // literal("-")) | Product);
 
Sum;</lang>
 
=== Evaluation ===
<lang jq># Left-to-right evaluation
def eval:
if type == "array" then
if length == 0 then null
else .[-1] |= eval
| if length == 1 then .[0]
else (.[:-2] | eval) as $v
| if .[-2] == "*" then $v * .[-1]
elif .[-2] == "/" then $v / .[-1]
elif .[-2] == "+" then $v + .[-1]
elif .[-2] == "-" then $v - .[-1]
else tostring|error
end
end
end
else .
end;
 
def eval(String):
{remainder: String}
| Expr.result
| eval;</lang>
 
=== Example ===
eval("2 * (3 -1) + 2 * 5")
 
produces: 14
 
=={{header|Jsish}}==
2,464

edits