Engee documentation
Notebook

Calculating arithmetic expressions

This example demonstrates how you can use the built-in Julia parser to analyze and calculate arithmetic expressions.

Introduction

The calculation of arithmetic expressions is the process by which the string representation of a mathematical expression is transformed into a data structure that can be interpreted and calculated. It is a key element of many software systems, such as calculators, compilers, and interpreters.

This process usually involves two main steps:

  1. Parsing - converting a string into abstract syntactic дерево (AST)
  2. Calculation - traversing the tree and performing mathematical operations

This approach is used in:

  • Compilers and interpreters of programming languages
  • Mathematical calculators
  • Computer algebra systems
  • Analysis of mathematical expressions in scientific computing

Working with an expression in Julia

Julia provides built-in functions for working with expressions and calculating them. Function Meta.parse() converts a string with a code into an object of the type Expr (expression), which is an abstract syntax tree.

In [ ]:
# Определяем строку с арифметическим выражением
expr = "2 * (3 -1) + 2 * 5"
Out[0]:
"2 * (3 -1) + 2 * 5"
In [ ]:
# Преобразуем строку в выражение (AST)
parsed = Meta.parse(expr) # Julia предоставляет низкоуровневый доступ к парсеру языка для создания AST/Expr
Out[0]:
:(2 * (3 - 1) + 2 * 5)

After parsing, we get an object of the type Expr, which is an abstract syntax tree (AST). This is a tree structure where each node corresponds to an operation or operand.

In [ ]:
# Получаем тип объекта
t = typeof(parsed)
Out[0]:
Expr

An object of the type Expr has fields:

  • :head — node type (for example, addition operation :+)
  • :args — node arguments (operands)
In [ ]:
# Просматриваем поля типа Expr
fieldnames(t) # показывает поля типа
Out[0]:
(:head, :args)

The main field for us is args, which contains the arguments of the expression.
For our expression, the first argument is an operation symbol. :+, and the rest of the arguments are subexpressions.

In [ ]:
# Исследуем внутреннюю структуру объекта 'Expr'
parsed.args # Инспектируем содержимое типа 'Expr'
Out[0]:
3-element Vector{Any}:
 :+
 :(2 * (3 - 1))
 :(2 * 5)

As you can see, expressions can be nested. The second argument of our expression is also an object of type Expr.

In [ ]:
# Типы 'Expr' могут быть вложенными
typeof(parsed.args[2])
Out[0]:
Expr
In [ ]:
# Смотрим аргументы вложенного выражения
parsed.args[2].args
Out[0]:
3-element Vector{Any}:
  :*
 2
  :(3 - 1)

Going deeper down the tree, we reach the most basic elements — numbers and simple operations.

In [ ]:
# Продолжаем спускаться до самого нижнего уровня AST
parsed.args[2].args[3].args # Будет вкладываться до самого низкого уровня AST
Out[0]:
3-element Vector{Any}:
  :-
 3
 1

Finally, when the tree is built, we can calculate the result using the function eval().

In [ ]:
# Вычисляем выражение
eval(parsed)
Out[0]:
14

Additional examples

Let's demonstrate how the algorithm works on other expressions.:

In [ ]:
# Более сложное выражение с делением
eval(Meta.parse("1 - 5 * 2 / 20 + 1"))
Out[0]:
1.5
In [ ]:
# Выражение с несколькими уровнями вложенности скобок
eval(Meta.parse("2 * (3 + ((5) / (7 - 11)))"))
Out[0]:
3.5

Conclusion

We have reviewed the implementation of the algorithm for calculating arithmetic expressions in Julia, using the built-in language features for parsing and calculating expressions.

We succeeded:

  1. Convert the string representation of a mathematical expression into an abstract syntax tree (AST)

  2. Investigate the structure of the resulting tree

  3. Perform the calculation of the expression, taking into account the priority of operations and parentheses.

This approach is useful for:

  • Creation of mathematical calculators
  • DSL (Domain-specific languages) development
  • Building compilers and interpreters
  • Analysis and processing of mathematical expressions in scientific applications

The example was developed using materials from Rosetta Code