# Формальное описание синтаксиса выражений SMath Studio (расширенная БНФ)

## Общие положения

- Используется EBNF (расширенная форма Бэкуса–Наура)
- Пробелы между элементами **не допускаются** во внутреннем строковом представлении, кроме содержимого внутри строковых литералов (в двойных кавычках)
- Символ `:` означает оператор присваивания (отображается как `:=`)
- Символ `=` используется **только** в пользовательском интерфейсе как обозначение вывода результата, во внутреннем представлении — не используется
- Все символы, кроме букв/цифр в строках, кодируются как `\XXXX\` — 4-значный Unicode между двумя обратными слэшами
- Пустая строка (`""`) допустима
- Внутри строк **нельзя** использовать символы управления (например, `\n`, `\r` и т.п.) или символ `=` — он зарезервирован для вывода результата
- В именах переменных поддерживаются **Unicode-символы**, включая греческие: пример допустимого имени — `α`
- Символ **точки** в имени переменной разрешён, но визуально означает нижний индекс: `R.test` — отображается как `Rₜₑₛₜ`
- При задании **десятичных чисел** можно опустить целую часть: `.5` интерпретируется как `0.5`
- **Экспоненциальная запись с ****\`\`**** не поддерживается**: `1.2e-6` — недопустимо; следует использовать `1.2*10^{-6}`
- Приближённое сравнение (`≈`) использует значение ε, заданное в настройках SMath Studio, и по умолчанию точность равна трём (3) знакам после запятой
- Все функции должны иметь **как минимум один аргумент**
- Функции могут быть определены через арифметическое выражение либо программный блок (например, с использованием `line()`)

---

## 1. Базовые правила

```ebnf
<expression>       ::= <assignment> | <function_call> | <binary_expr> | <rel_expr> | <logic_expr> | <literal> | <variable>

<assignment>       ::= <variable> ":" <expression>                      (* Присваивание *)
<function_call>    ::= <identifier> "(" <arguments> ")"                (* Вызов функции *)
<binary_expr>      ::= <expression> <binary_op> <expression>
<rel_expr>         ::= <expression> <rel_op> <expression>
<logic_expr>       ::= <expression> <logic_op> <expression>
                   | "¬" <expression>

<arguments>        ::= <expression> { "," <expression> }

<binary_op>        ::= "+" | "-" | "*" | "/" | "^"
<rel_op>           ::= "≡" | "≠" | "<" | ">" | "≤" | "≥" | "≈" | "≉"
<logic_op>         ::= "&" | "|" | "⨁"

<literal>          ::= <number> | <string>
<number>           ::= [ <digit> { <digit> } ] "." <digit> { <digit> } 
<string>           ::= '"' { <printable_char> | <escaped_unicode> } '"'
<escaped_unicode>  ::= "\\" <hex_digit><hex_digit><hex_digit><hex_digit> "\\"

<variable>         ::= <identifier>
<identifier>       ::= <unicode_letter> { <unicode_letter> | <digit> | "_" | "." }
<digit>            ::= "0" | "1" | ... | "9"
<unicode_letter>   ::= любой допустимый Unicode-символ, включая греческие и специальные
<printable_char>   ::= любой печатный символ Unicode, кроме управляющих и `=` внутри строк
```

---

## 2. Примеры соответствия EBNF и представлений

(... предыдущие примеры опущены для краткости ...)

### Пример 6: Подготовка данных для круговой (радарной) диаграммы

**Определение функции:**

```
XYRadar(A,a,b):line(
  mat(g:{360*(range(1,rows(A))-1)}/rows(A),Ρ:range(0,a,b),M:sys("M",1,1),1,3),
  mat(XY(a):augment(vectorize(a*cos(g*'°)),vectorize(a*sin(g*'°))),XY:XY(a),1,2),
  mat(k:range(0,a/b)+1,C:0,el(C,k):(k-1)*b/a*stack(XY,row(XY,1)),1,3),
  mat(k:range(1,rows(g)),L:0,el(L,k):stack(mat(0,0,1,2),row(XY,k)),1,3),
  G:augment(XY+0.15*a*augment(-vectorize(ltlt(g,90,270)),vectorize(lele(g,0,180))),vectorize(num2str(k))),
  for(c,range(1,cols(A)),el(M,c+2):eval(stack(m:XY(col(A,c)),row(m,1)))),
  el(M,1):stack(C,L),
  el(M,2):augment(stack(G,augment(0,Ρ,vectorize(var2str(Ρ,1)))),9),
  8,1
)
```

**Назначение элементов:**

- `mat(...)` — создание матрицы с параметрами: выражения и размерность
- `augment(...)`, `stack(...)` — горизонтальное и вертикальное объединение
- `vectorize(...)` — преобразование выражения поэлементно к вектору
- `sys("M",1,1)` — создание системной матрицы
- `el(...)` — доступ/присваивание элемента матрицы
- `line(...)` — объединение программных шагов (выполнение по порядку)
- `for(...)` — встроенный цикл с присваиванием в теле
- `ltlt(a,b,c)`, `lele(a,b,c)` — булевы маски (a > b и a ≤ c соответственно)

**Тип выражения:** программный блок, возвращающий матрицу `M`, подготовленную для отображения графического радара по данным `A`

---

... (предыдущий текст без изменений) ...

### Пример 7: Формирование полярной сетки и отображение функции

**Определение функции:**

```
XYPolar(a,b):line(
  if(length(stack(a))≡1,
    line(
      F(f,z,clr):transpose(mat(f,transpose(z),clr,"solid",1,1,5)),
      mat(g:range(0,330,30),g°:vectorize(concat(num2str(g),"\00B0\")),Ρ:range(0,a,b),1,3),
      mat(X,Y,1,2):a*mat(vectorize(cos(g*'°)),vectorize(sin(g*'°)),1,2),
      mat(k:range(1,a/b),C:0,el(C,k):F("circle",mat(0,0,(k-1)*b,1,3),"gray"),1,3),
      mat(k:range(1,length(g)),L:0,el(L,k):F("line",mat(0,0,el(X,k),el(Y,k),1,4),"gray"),1,3),
      G:augment(X-0.25*a*vectorize(ltlt(g,90,270)),Y+0.15*a*vectorize(lele(g,0,180)),g°),
      sys(mat(stack(L,C,mat(F("circle",mat(0,0,a,1,3),"black"),1,1)),1,1),augment(stack(G,augment(0,Ρ,vectorize(var2str(Ρ,1)))),9),2,1),
      7,1
    ),
    augment(vectorize(b*cos(a)),vectorize(b*sin(a)))
  ),
  1,1
)
```

**Назначение элементов:**

- `if(...)` — переключение между режимом сетки и одиночной кривой в зависимости от размера `a`
- `F(f,z,clr):...` — вложенная функция с параметрами: тип фигуры, параметры и цвет
- `g` — углы (в градусах), `Ρ` — радиальные координаты
- `g°` — текстовые подписи углов в формате `"30°"`
- `X,Y` — координаты точек окружности
- `el(...)` — доступ/запись в матрицу по индексу
- `ltlt(g,90,270)`, `lele(g,0,180)` — логические маски (диапазоны углов)
- `sys(...)` — результат, подаваемый компоненту визуализации

**Использование:**

```
sys(XYPolar(2,0.5),XYPolar(φ:range(0,359,1)*'°,vectorize(1+cos(φ))),2,1)
```

— отрисовывает полярную сетку и график функции `r = 1 + cos(φ)`.

**Тип выражения:** программный блок, возвращающий структуру данных для графической визуализации в полярных координатах

---

... (предыдущий текст без изменений) ...

### Пример 7: Формирование полярной сетки и отображение функции

**Определение функции:**

```
XYPolar(a,b):line(
  if(length(stack(a))≡1,
    line(
      F(f,z,clr):transpose(mat(f,transpose(z),clr,"solid",1,1,5)),
      mat(g:range(0,330,30),g°:vectorize(concat(num2str(g),"\00B0\")),Ρ:range(0,a,b),1,3),
      mat(X,Y,1,2):a*mat(vectorize(cos(g*'°)),vectorize(sin(g*'°)),1,2),
      mat(k:range(1,a/b),C:0,el(C,k):F("circle",mat(0,0,(k-1)*b,1,3),"gray"),1,3),
      mat(k:range(1,length(g)),L:0,el(L,k):F("line",mat(0,0,el(X,k),el(Y,k),1,4),"gray"),1,3),
      G:augment(X-0.25*a*vectorize(ltlt(g,90,270)),Y+0.15*a*vectorize(lele(g,0,180)),g°),
      sys(mat(stack(L,C,mat(F("circle",mat(0,0,a,1,3),"black"),1,1)),1,1),augment(stack(G,augment(0,Ρ,vectorize(var2str(Ρ,1)))),9),2,1),
      7,1
    ),
    augment(vectorize(b*cos(a)),vectorize(b*sin(a)))
  ),
  1,1
)
```

**Назначение элементов:**

- `if(...)` — переключение между режимом сетки и одиночной кривой в зависимости от размера `a`
- `F(f,z,clr):...` — вложенная функция с параметрами: тип фигуры, параметры и цвет
- `g` — углы (в градусах), `Ρ` — радиальные координаты
- `g°` — текстовые подписи углов в формате `"30°"`
- `X,Y` — координаты точек окружности
- `el(...)` — доступ/запись в матрицу по индексу
- `ltlt(g,90,270)`, `lele(g,0,180)` — логические маски (диапазоны углов)
- `sys(...)` — результат, подаваемый компоненту визуализации

**Использование:**

```
sys(XYPolar(2,0.5),XYPolar(φ:range(0,359,1)*'°,vectorize(1+cos(φ))),2,1)
```

— отрисовывает полярную сетку и график функции `r = 1 + cos(φ)`.

**Тип выражения:** программный блок, возвращающий структуру данных для графической визуализации в полярных координатах

---

... (предыдущий текст без изменений) ...

### Пример 8: Разложение в ряд Фурье

**Определение функции:**

```
v(n,t):el(a,1)/2 + sum(el(a,k+1)*cos(k*ω.1*t) + el(b,k+1)*sin(k*ω.1*t), k, 1, n)
```

**Назначение элементов:**

- `el(a,k+1)` — коэффициенты косинусного ряда
- `el(b,k+1)` — коэффициенты синусного ряда
- `ω.1` — частота первой гармоники (переменная с индексом `.1`)
- `sum(expr, k, 1, n)` — суммирование выражения по переменной `k` от `1` до `n`
- `el(a,1)/2` — постоянная (средняя) составляющая ряда

**Тип выражения:** аналитическая функция времени `t` и числа гармоник `n`, строящаяся как сумма синусоидальных компонент с заданными амплитудами по формулам Фурье.

**Дополнительно:**

- Поддерживается использование переменных с точками в имени (`ω.1`) — интерпретируется как нижний индекс в визуализации
- Сумма выражений допускает вложенные арифметические и тригонометрические операции

---

... (предыдущий текст без изменений) ...

### Пример 9: Стандартные функции из палитры «Матрицы»

Ниже приведены встроенные функции SMath Studio, доступные в палитре **Матрицы**. Примеры даны с использованием плейсхолдера `#` вместо фактических аргументов.

**Определения:**

- **Определение матрицы:**

  ```
  mat(#,#,#,#,#,#,#,#,#,3,3)   // элементы + размерность (3 строки, 3 столбца)
  ```

- **Определитель матрицы:**

  ```
  det(#)
  ```

- **Транспонирование матрицы:**

  ```
  transpose(#)
  ```

- **Алгебраическое дополнение:**

  ```
  alg(#,#,#)   // матрица, строка, столбец
  ```

- **Минор:**

  ```
  minor(#,#,#) // матрица, строка, столбец
  ```

- **Векторное умножение (векторный оператор):**

  ```
  #†#
  ```

- **Векторизация:**

  ```
  vectorize(#)
  ```

- **Диапазон значений:**

  ```
  range(#,#)           // от, до
  range(#,#,#)         // от, шаг, до
  ```

  > Замечание: третий аргумент определяет шаг; второй — границу диапазона

- **Обращение к элементу вектора:**

  ```
  el(#,#)              // вектор, индекс
  ```

- **Обращение к элементу матрицы:**

  ```
  el(#,#,#)            // матрица, строка, столбец
  ```

**Особенности:**

- Все функции допускают как символьные, так и численные аргументы
- Операторы `†`, `el(...)` и `range(...)` часто используются в графических и символьных построениях
- Порядок аргументов в функциях фиксирован и соответствует реализации в интерфейсе SMath

---

... (предыдущий текст без изменений) ...

### Пример 12: Передача функций в качестве аргументов

SMath Studio поддерживает передачу **функций как аргументов** другим функциям. Это позволяет реализовывать функциональное программирование и повторно использовать определённые правила вычислений.

**Пример 1: Передача через шаблон вызова**

```
g(a,b):a+b
f(x,y,g(x#,y#)):line(sum:g(x,y),sum,2,1)
f(1,2,g(a,b)) = 3
```

- `g(a,b)` — функция сложения
- `f(x,y,g(...))` — обобщённая функция, в которую передаётся `g` с шаблоном `g(x#,y#)`
- Символ `#`, может использоваться, чтобы визуально отличать локальные аргументы от глобальных

**Пример 2: Указание количества параметров вместо формальных**

```
g(a,b):a+b
f(x,y,g(2)):line(sum:g(x,y),sum,2,1)
f(3,4,g(a,b)) = 7
```

- В `g(2)` - функция g с двумя параметрами
- После подстановки: `g(3,4)` → `3+4 = 7`, далее с `sum` и `line(...)` даёт итоговое значение
- Такие конструкции поддерживают символьную интерпретацию и вычисление

---

