Arithmetic evaluation: Difference between revisions

m
Automated syntax highlighting fixup (second round - minor fixes)
m (syntax highlighting fixup automation)
m (Automated syntax highlighting fixup (second round - minor fixes))
Line 1:
{{task}}[[Category:Recursion]]
{{task}}Create a program which parses and evaluates arithmetic expressions.
 
;Requirements:
Line 25:
=={{header|11l}}==
[[wp:Pratt parser|Pratt parser]]
<syntaxhighlight lang="11l">T Symbol
String id
Int lbp
Line 154:
{{works with|ALGOL 68G|Any - tested with release [http://sourceforge.net/projects/algol68/files/algol68g/algol68g-1.18.0/algol68g-1.18.0-9h.tiny.el5.centos.fc11.i386.rpm/download 1.18.0-9h.tiny]}}
{{wont work with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release [http://sourceforge.net/projects/algol68/files/algol68toc/algol68toc-1.8.8d/algol68toc-1.8-8d.fc9.i386.rpm/download 1.8-8d] - A68RS has not implemented forward declarations}}
<syntaxhighlight lang="algol68">INT base=10;
MODE FIXED = LONG REAL; # numbers in the format 9,999.999 #
 
Line 303:
=={{header|AutoHotkey}}==
{{works with|AutoHotkey_L}}
<syntaxhighlight lang=AutoHotkey"autohotkey">/*
hand coded recursive descent parser
expr : term ( ( PLUS | MINUS ) term )* ;
Line 453:
 
#include calclex.ahk</syntaxhighlight>
calclex.ahk<syntaxhighlight lang=AutoHotkey"autohotkey">tokenize(string, lexer)
{
stringo := string ; store original string
Line 523:
=={{header|BBC BASIC}}==
{{works with|BBC BASIC for Windows}}
<syntaxhighlight lang="bbcbasic"> Expr$ = "1 + 2 * (3 + (4 * 5 + 6 * 7 * 8) - 9) / 10"
PRINT "Input = " Expr$
AST$ = FNast(Expr$)
Line 595:
 
{{libheader|Boost.Spirit|1.8.4}}
<syntaxhighlight lang="cpp"> #include <boost/spirit.hpp>
#include <boost/spirit/tree/ast.hpp>
#include <string>
Line 713:
 
=={{header|Clojure}}==
<syntaxhighlight lang=Clojure"clojure">(def precedence '{* 0, / 0
+ 1, - 1})
 
Line 783:
This implementation can read integers, and produce integral and rational values.
 
<syntaxhighlight lang="lisp">(defun tokenize-stream (stream)
(labels ((whitespace-p (char)
(find char #(#\space #\newline #\return #\tab)))
Line 912:
=={{header|D}}==
After the AST tree is constructed, a visitor pattern is used to display the AST structure and calculate the expression value.
<syntaxhighlight lang="d">import std.stdio, std.string, std.ascii, std.conv, std.array,
std.exception, std.traits;
 
Line 1,154:
=={{header|Dyalect}}==
 
<syntaxhighlight lang="dyalect">type Expr = Bin(op, Expr left, Expr right) or Literal(Float val)
with Lookup
 
Line 1,282:
While the task requirements specify not evaluating using the language's built-in eval, they don't say that you have to write your own ''parser''...
 
<syntaxhighlight lang="e">def eParser := <elang:syntax.makeEParser>
def LiteralExpr := <elang:evm.makeLiteralExpr>.asType()
def arithEvaluate(expr :String) {
Line 1,303:
Parentheses are handled by the parser.
 
<syntaxhighlight lang="e">? arithEvaluate("1 + 2")
# value: 3
 
Line 1,314:
=={{header|Elena}}==
ELENA 5.0 :
<syntaxhighlight lang="elena">import system'routines;
import extensions;
import extensions'text;
Line 1,657:
 
=={{header|Emacs Lisp}}==
<syntaxhighlight lang="lisp">#!/usr/bin/env emacs --script
;; -*- mode: emacs-lisp; lexical-binding: t -*-
;;> ./arithmetic-evaluation '(1 + 2) * 3'
Line 1,772:
 
=={{header|ERRE}}==
<syntaxhighlight lang=ERRE"erre">
PROGRAM EVAL
 
Line 2,013:
 
<code>AbstractSyntaxTree.fs</code>:
<syntaxhighlight lang="fsharp">module AbstractSyntaxTree
type Expression =
Line 2,023:
 
<code>Lexer.fsl</code>:
<syntaxhighlight lang="fsharp">{
module Lexer
 
Line 2,049:
 
<code>Parser.fsy</code>:
<syntaxhighlight lang="fsharp">%{
open AbstractSyntaxTree
%}
Line 2,077:
 
<code>Program.fs</code>:
<syntaxhighlight lang="fsharp">open AbstractSyntaxTree
open Lexer
open Parser
Line 2,100:
 
=={{header|Factor}}==
<syntaxhighlight lang="factor">USING: accessors kernel locals math math.parser peg.ebnf ;
IN: rosetta.arith
 
Line 2,144:
 
=={{header|FreeBASIC}}==
<syntaxhighlight lang=FreeBASIC"freebasic">
'Arithmetic evaluation
'
Line 2,355:
=={{header|Groovy}}==
Solution:
<syntaxhighlight lang="groovy">enum Op {
ADD('+', 2),
SUBTRACT('-', 2),
Line 2,501:
 
Test:
<syntaxhighlight lang="groovy">def testParse = {
def ex = parse(it)
print """
Line 2,605:
 
=={{header|Haskell}}==
<syntaxhighlight lang="haskell">{-# LANGUAGE FlexibleContexts #-}
 
import Text.Parsec
Line 2,667:
* Notice that the code looks remarkably like a typical grammar, rather than being an opaque cryptic solution
* Does not rely on any library to silently solve 1/2 the problem; in fact, this code would probably suit being put into a library almost verbatim
<syntaxhighlight lang=Icon"icon">procedure main() #: simple arithmetical parser / evaluator
write("Usage: Input expression = Abstract Syntax Tree = Value, ^Z to end.")
repeat {
Line 2,799:
The implementation here uses a shift/reduce parser to build a tree structure for evaluation (a tree structure which J happens to support for evaluation):
 
<syntaxhighlight lang="j">parse=:parse_parser_
eval=:monad define
'gerund structure'=:y
Line 2,866:
)</syntaxhighlight>
example use:
<syntaxhighlight lang="j"> eval parse '1+2*3/(4-5+6)'
2.2</syntaxhighlight>
 
You can also display the syntax tree, for example:
<syntaxhighlight lang="j"> parse '2*3/(4-5)'
┌─────────────────────────────────────────────────────┬───────────────────┐
│┌───┬───────┬───┬───────┬───┬─┬───────┬───┬───────┬─┐│┌───────┬─┬───────┐│
Line 2,887:
Uses the [[Arithmetic/Rational/Java|BigRational class]] to handle arbitrary-precision numbers (rational numbers since basic arithmetic will result in rational values).
 
<syntaxhighlight lang="java">import java.util.Stack;
 
public class ArithmeticEvaluation {
Line 3,066:
Spaces are removed, expressions like <code>5--1</code> are treated as <code>5 - -1</code>
 
<syntaxhighlight lang="javascript">function evalArithmeticExp(s) {
s = s.replace(/\s/g,'').replace(/^\+/,'');
var rePara = /\([^\(\)]*\)/;
Line 3,136:
 
=== PEG operations ===
<syntaxhighlight lang="jq">def star(E): (E | star(E)) // .;
def plus(E): E | (plus(E) // . );
def optional(E): E // .;
Line 3,144:
 
=== Helper functions ===
<syntaxhighlight lang="jq">def literal($s):
select(.remainder | startswith($s))
| .result += [$s]
Line 3,168:
 
=== PEG Grammar ===
The PEG grammar for arithmetic expressions follows the one given at the Raku entry.<syntaxhighlight lang="jq">def Expr:
 
def ws: consume(" *");
Line 3,183:
 
=== Evaluation ===
<syntaxhighlight lang="jq"># Left-to-right evaluation
def eval:
if type == "array" then
Line 3,214:
From Javascript entry.
 
<syntaxhighlight lang="javascript">/* Arithmetic evaluation, in Jsish */
function evalArithmeticExp(s) {
s = s.replace(/\s/g,'').replace(/^\+/,'');
Line 3,303:
=={{header|Julia}}==
Julia's homoiconic nature and strong metaprogramming facilities make AST/Expression parsing and creation as accessible and programmatic as other language features
<syntaxhighlight lang="julia">julia> expr="2 * (3 -1) + 2 * 5"
"2 * (3 -1) + 2 * 5"
 
Line 3,347:
=={{header|Kotlin}}==
{{trans|JavaScript}}
<syntaxhighlight lang="scala">// version 1.2.10
 
/* if string is empty, returns zero */
Line 3,449:
 
=={{header|Liberty BASIC}}==
<syntaxhighlight lang="lb">
'[RC] Arithmetic evaluation.bas
'Buld the tree (with linked nodes, in array 'cause LB has no pointers)
Line 3,703:
=={{header|Lua}}==
 
<syntaxhighlight lang="lua">require"lpeg"
 
P, R, C, S, V = lpeg.P, lpeg.R, lpeg.C, lpeg.S, lpeg.V
Line 3,748:
All visible variables can be used, and all known functions, internal and user (if they are visible at that point). Global variables and functions are always visible.
 
<syntaxhighlight lang=M2000"m2000 Interpreterinterpreter">
y=100
Module CheckEval {
Line 3,765:
From BBC BASIC. In M2000 we can't call a user function which isn't a child function, so here we make all functions as members of same group, so now they call each other. A function as a member in a group can use other members, using a dot or This and a dot, so .Ast$() is same as This.Ast$().
 
<syntaxhighlight lang=M2000"m2000 Interpreterinterpreter">
Module CheckAst {
Group Eval {
Line 3,822:
 
=={{header|Mathematica}} / {{header|Wolfram Language}}==
<syntaxhighlight lang=Mathematica"mathematica">(*parsing:*)
parse[string_] :=
Module[{e},
Line 3,858:
 
Example use:
<syntaxhighlight lang=Mathematica"mathematica">parse["-1+2(3+4*-5/6)"]
evaluate["-1+2(3+4*-5/6)"]</syntaxhighlight>
 
Line 3,866:
 
=={{header|MiniScript}}==
<syntaxhighlight lang=MiniScript"miniscript">Expr = {}
Expr.eval = 0
 
Line 3,947:
This implementation uses a Pratt parser.
 
<syntaxhighlight lang="nim">import strutils
import os
 
Line 4,101:
=={{header|OCaml}}==
 
<syntaxhighlight lang="ocaml">type expression =
| Const of float
| Sum of expression * expression (* e1 + e2 *)
Line 4,143:
Using the function <code>read_expression</code> in an interactive loop:
 
<syntaxhighlight lang="ocaml">let () =
while true do
print_string "Expression: ";
Line 4,157:
 
=={{header|ooRexx}}==
<syntaxhighlight lang=ooRexx"oorexx">
expressions = .array~of("2+3", "2+3/4", "2*3-4", "2*(3+4)+5/6", "2 * (3 + (4 * 5 + (6 * 7) * 8) - 9) * 10", "2*-3--4+-.25")
loop input over expressions
Line 4,410:
The <code>Do</code> procedure automatically threads the input state through a sequence of procedure calls.
 
<syntaxhighlight lang="oz">declare
 
fun {Expr X0 ?X}
Line 4,506:
 
=={{header|Perl}}==
<syntaxhighlight lang="perl">sub ev
# Evaluates an arithmetic expression like "(1+3)*7" and returns
# its value.
Line 4,573:
plus this as asked for has an AST, whereas Phix uses cross-linked flat IL.
See also [[Arithmetic_evaluation/Phix]] for a translation of the D entry.
<!--<syntaxhighlight lang=Phix"phix">(phixonline)-->
<span style="color: #000080;font-style:italic;">-- demo\rosetta\Arithmetic_evaluation.exw</span>
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
Line 4,867:
 
=={{header|Picat}}==
<syntaxhighlight lang=Picat"picat">main =>
print("Enter an expression: "),
Str = read_line(),
Line 4,879:
(numbers and transient symbols). From that, a recursive descendent parser can
build an expression tree, resulting in directly executable Lisp code.
<syntaxhighlight lang=PicoLisp"picolisp">(de ast (Str)
(let *L (str Str "")
(aggregate) ) )
Line 4,903:
((= "(" X) (prog1 (aggregate) (pop '*L)))) ) )</syntaxhighlight>
{{out}}
<syntaxhighlight lang=PicoLisp"picolisp">: (ast "1+2+3*-4/(1+2)")
-> (+ (+ 1 2) (/ (* 3 (- 4)) (+ 1 2)))
 
Line 4,911:
=={{header|Pop11}}==
 
<syntaxhighlight lang="pop11">/* Scanner routines */
/* Uncomment the following to parse data from standard input
 
Line 5,063:
=={{header|Prolog}}==
{{works with|SWI Prolog 8.1.19}}
<syntaxhighlight lang="prolog">% Lexer
numeric(X) :- 48 =< X, X =< 57.
not_numeric(X) :- 48 > X ; X > 57.
Line 5,119:
<br>A subsequent example uses Pythons' ast module to generate the abstract syntax tree.
 
<syntaxhighlight lang="python">import operator
 
class AstNode(object):
Line 5,238:
===ast standard library module===
Python comes with its own [http://docs.python.org/3.1/library/ast.html#module-ast ast] module as part of its standard libraries. The module compiles Python source into an AST tree that can in turn be compiled to bytecode then executed.
<syntaxhighlight lang="python">>>> import ast
>>>
>>> expr="2 * (3 -1) + 2 * 5"
Line 5,265:
=={{header|Racket}}==
 
<syntaxhighlight lang="racket">#lang racket
 
(require parser-tools/yacc
Line 5,306:
{{Works with|rakudo|2018.03}}
 
<syntaxhighlight lang=perl6"raku" line>sub ev (Str $s --> Numeric) {
 
grammar expr {
Line 5,366:
:::* &nbsp; 12.3D+44 &nbsp; &nbsp; &nbsp; ("double" precision)
:::* &nbsp; 12.3Q+44 &nbsp; &nbsp; &nbsp; ("extended" or "quad" precision)
<syntaxhighlight lang="rexx">/*REXX program evaluates an infix─type arithmetic expression and displays the result.*/
nchars = '0123456789.eEdDqQ' /*possible parts of a number, sans ± */
e='***error***'; $=" "; doubleOps= '&|*/'; z= /*handy─dandy variables.*/
Line 5,492:
=={{header|Ruby}}==
Function to convert infix arithmetic expression to binary tree. The resulting tree knows how to print and evaluate itself. Assumes expression is well-formed (matched parens, all operators have 2 operands). Algorithm: http://www.seas.gwu.edu/~csci131/fall96/exp_to_tree.html
<syntaxhighlight lang="ruby">$op_priority = {"+" => 0, "-" => 0, "*" => 1, "/" => 1}
 
class TreeNode
Line 5,593:
end</syntaxhighlight>
Testing:
<syntaxhighlight lang="ruby">exp = "1 + 2 - 3 * (4 / 6)"
puts("Original: " + exp)
 
Line 5,609:
 
=={{header|Rust}}==
<syntaxhighlight lang="rust">//! Simple calculator parser and evaluator
 
 
Line 5,788:
is practically non-existent, to avoid obscuring the code.
 
<syntaxhighlight lang="scala">
package org.rosetta.arithmetic_evaluator.scala
 
Line 5,864:
The parse function uses a recursive-descent parser to follow the precedence rules.
 
<syntaxhighlight lang="scheme">
(import (scheme base)
(scheme char)
Line 5,974:
=={{header|Sidef}}==
{{trans|JavaScript}}
<syntaxhighlight lang="ruby">func evalArithmeticExp(s) {
 
func evalExp(s) {
Line 6,032:
 
Testing the function:
<syntaxhighlight lang="ruby">for expr,res in [
['2+3' => 5],
['-4-3' => -7],
Line 6,049:
This implementation uses a [https://en.wikipedia.org/wiki/Recursive_descent_parser recursive descent parser]. It first lexes the input. The parser builds a Abstract Syntax Tree (AST) and the evaluator evaluates it. The parser uses sub categories.
The parsing is a little bit tricky because the grammar is left recursive.
<syntaxhighlight lang="sml">(* AST *)
datatype expression =
Con of int (* constant *)
Line 6,120:
 
=={{header|Tailspin}}==
<syntaxhighlight lang="tailspin">
def ops: ['+','-','*','/'];
 
Line 6,155:
 
If we don't need to get the AST, we could just evaluate right away:
<syntaxhighlight lang="tailspin">
composer calculator
(<WS>?) <addition|multiplication|term> (<WS>?)
Line 6,182:
in a form that it can be immediately eval-led,
using Tcl's prefix operators.
<syntaxhighlight lang=Tcl"tcl">namespace import tcl::mathop::*
 
proc ast str {
Line 6,241:
Use TXR text pattern matching to parse expression to a Lisp AST, then evaluate with <code>eval</code>:
 
<syntaxhighlight lang="txr">@(next :args)
@(define space)@/ */@(end)
@(define mulop (nod))@\
Line 6,303:
 
 
{{omit from|gnuplot}}
 
=={{header|Ursala}}==
with no error checking other than removal of spaces
<syntaxhighlight lang=Ursala"ursala">#import std
#import nat
#import flo
Line 6,327 ⟶ 6,326:
 
test program:
<syntaxhighlight lang=Ursala"ursala">#cast %eL
 
test = evaluate*t
Line 6,363 ⟶ 6,362:
{{trans|Kotlin}}
{{libheader|Wren-pattern}}
<syntaxhighlight lang="ecmascript">import "/pattern" for Pattern
 
/* if string is empty, returns zero */
Line 6,470 ⟶ 6,469:
=={{header|zkl}}==
In zkl, the compiler stack is part of the language and is written in zkl so ...
<syntaxhighlight lang="zkl">Compiler.Parser.parseText("(1+3)*7").dump();
Compiler.Parser.parseText("1+3*7").dump();</syntaxhighlight>
The ASTs look like
Line 6,493 ⟶ 6,492:
</pre>
Evaluating them is just moving up the stack:
<syntaxhighlight lang="zkl">Compiler.Compiler.compileText("(1+3)*7").__constructor(); vm.regX;
Compiler.Compiler.compileText("1+3*7").__constructor(); vm.regX;</syntaxhighlight>
{{out}}
Line 6,502 ⟶ 6,501:
 
=={{header|ZX Spectrum Basic}}==
<syntaxhighlight lang="zxbasic">10 PRINT "Use integer numbers and signs"'"+ - * / ( )"''
20 LET s$="": REM last symbol
30 LET pc=0: REM parenthesis counter
Line 6,534 ⟶ 6,533:
310 STOP
</syntaxhighlight>
{{omit from|gnuplot}}
10,327

edits