LINUX.ORG.RU

История изменений

Исправление geekless, (текущая версия) :

Я тут нашел описание грамматики выражений какого-то своего черновика ЯП, который набросал лет 5 назад. В общем, я просто оставлю это здесь. (Я не знаю, чем я упарывался.)

Приоритет и ассоциативность операций.

left             `
left             or
left             and
right            =, bin_op=
left             ? :?
left             ||
left             &&
left             |
left             ~
left             &
non-associative  ==, !=
non-associative  <, <=, >, >=
non-associative  in
left             shl, shr, rol, ror
left             +, -, 
left             *, /, -/
left             \r
right            \b, \rd
left             :...
left             :., операции объединения
left             ::, :*, операции поиска и выборки
left             as
right            !, ~(унарная), +(унарная), -(унарная), new, %..., <>...
right            ++ --
left             ^
left             ., ->, [], (), of


Простые операции.



Арифметические:
+(унарная) пустая операция
-(унарная) смена знака
+ сложение 
- вычитание
* умножение
/ деление
-/ взятие остатка
Для взятия остатка выбрана такая операция, поскольку -/ можно воспринимать
как сокращение a - a / b. По аналогии с конструкциями вида a += b логичнее
было бы /-, но это конфликтует с унарным минусом: a/-b.

Побитовые:
shr сдвиг вправо
shl сдвиг влево
ror вращение вправо
rol вращение влево
~   побитовое исключающее или
|   обитовое или
&   побитовое и
~(унарная) побитовое отрицание

Равенства:
== равно
!= не равно

Сравнения:
<  меньше
<= меньше или равно
>  больше
>= больше или равно

Логические:
&& логическое и
|| логическое или
!(унарная) логическое отрицание
and, or, not - аналогично, но с иным приоритетом.


Выборки:
:: выборка элемента из контейнера по ключу
:* выборка элементов из контейнера по ключам

vec::i // i-й элемент в vec, аналогично vec[i]
vec:*[1...10, 4] // выбрать с 1-го по 10-й, а затем 4-й (повторно)

Поиска и выборки:
Данные операции конструируются по следующему шаблону:
":" "!"? (">" | "<" | "*") ("<" | "<=" | ">" | ">=" | "!=" | "==" | "/")
Если имеется "!", результатом служит ключ(ключи) найденного
элемента(элементов), иначе - значение элемента.
Если далее идёт ">", поиск осуществляется от начала к концу,
если "<" - от конца к началу, если "*" - поиск осуществляется
по всему контейнеру и тип результата - контейнер с выбранными
элементами. Далее указывается либо:
1) либо одна из операций "<", "<=", ">", ">=", "!=", "==",
в этом случае осуществляется поиск элемента, для которого
данная операция истинна (при сравнении со вторым операндом),
2) либо символ "/", в этом случае второй операнд - функция-фильтр.
Примеры:
vec:!<==' ' // возвращает ключ элемента со значением ' ', поиск с конца
vec:>/filter // возвращает значение элемента, для которого filter вернул true, поиск с начала

vec:*/filter // выбрать все элементы, для которых функция filter вернула true


in имеется ли в контейнере (второй операнд) элемент, равный первому операнду

' ' in vec


Конкатенации:
:. конкатенация

vec = ['a', 'b', ' ', '0'];
vec:.['q', 'w'] // ['a', 'b', ' ', '0', 'q', 'w']


Объединения:
Данные операции конструируются по следующему шаблону:
":" операция_для_уникальных_ключей операция_для_неуникальных_ключей.
Два контейнера объединяются по ключам.
Ключи, которые имеются только в одном контейнере:
*  включать элементы из обоих контейнеров
1  включать элементы из левого контейнера
2  включать элементы из правого контейнера
0  не включать эти элементы
Ключи, которые имеются в обоих контейнерах:
1  включать значения элементов из левого контейнера
2  включать значения элементов из правого контейнера
== включить только совпадающие в обоих контейнерах значения
!= включить только не совпадающие в обоих контейнерах значения
>  включать большее значение
<  включать меньшее значение
0  не включать эти элементы
Примечание. Сочетания :11, :22, :00 разрешены. Результат, соотвественно,
левый контейнер, правый контейнер и пустой контейнер.

Примеры:
v1:0==v2 // найти пары ключ-значение, общие для обоих контейнеров
v1:20 v2 // найти пары элементы с уникальным ключём в правом контейнере


Приведения типа:
as - привести к указанному типу
a as integer // привести a к типу integer


Присваивания:
= присваивание



Выражения-операции.

Инверсия.
bin_op : "\" bin_op;
Значение: a "\" bin_op b === b bin_op a

Сложное присваивание.
bin_op : bin_op "=";
Значение: a bin_op "=" b === a "=" a bin_op b

Выбор.
bin_op : "??" bin_op;
Значение: a "??" bin_op b === a bin_op b "?" a ":" b

Примеры:
a ??> b // большее из a и b



Свёртка. (Reduce)
un_op : "\r" bin_op;
Значение: "\r" bin_op a === {if %len a == 0, raise Exc; auto i = %iterator a; __result = i++^; foreach auto v in i, __result bin_op= v;}

Свёртка со значением по умолчанию. (Reduce with Default)
bin_op : "\rd" bin_op;
Значение: b "\rd" bin_op a === {__result = b; auto i = %iterator a; foreach auto v in i, __result bin_op= v;}

Примеры:
\r+[1, 2, 3] // 1 + 2 + 3
5 \rd+[1, 2, 3] // 5 + 1 + 2 + 3
a\rd??>=vec; // Среди значения a и всех значений
контейнера vec выбрать максимальное при присвоить a.

Разветвление. (Branch)
un_op : "\b" un_op*(1) "{" bin_op "}" un_op*(2) ;
Значение: "\b" un_op*(1) "{" bin_op "}" un_op*(2) a === (un_op*(1) a) bin_op (un_op*(2) a)

Примеры:
\b\r+{/}%len v // то же самое, что (\r+ v) / (%len v), т.е. вычисление среднего арифметического элементов v

Понижение до унарной операции.
(Объединение последовательности бинарных операций в унарную.)
un_op : "%" "{" bin_op expression { "," bin_op expression}  "}" ;
Значение: "%" "{" bin_op expression { "," bin_op expression}  "}" a === алгоритм:
1) __result(0) = a;
2) для каждого i-го фрагмента вида bin_op expression,
__result(i) = __result(i-1) bin_op(i) expression(i);
Следует обратить внимание, что переменные __result(0),
__result(1), __result(2) и т.п. - это разные переменные, могущие иметь разные типы.


\b \r+%{:/filter1} {/} \r+%{:/filter2} v
// Выбирает из v элементы по фильтру filter1, ищет их сумму;
// выбирает из v элементы по фильтру filter2, ищет их сумму;
// находит частное от сумм.

Векторизация бинарной операции.
bin_op: "bin_op" "<" a1 a2 ">"
Значение: бинарная операция применяется к парам значений
(с совпадающими ключами) из двух контейнеров. Параметры a1 и a1
указывают, как поступать с элементами (соотвественно, в левом и
правом контейнере), которые не имеют пары:
"e" - иницировать исключение при встрече такого элемента
"i" - игнорировать такие элементы и не включать в контейнер-результат
"r" помещать такие элементы в контейнер результат без выполнения над ним вычислений
"{" expression "}" использовать в качестве пары
    значение expression (значение вычисляет один раз в начале
    выполнения векторизованной операции)
"!{" expression "}" использовать в качестве пары
    значение expression (значение вычисляет для каждой пары
    заново)
"l" использовать в качестве пары значение, свойства last
    другого контейнера
"f" использовать в качестве пары значение, свойства first
    другого контейнера
Если a2 отсуствует, подразумевается "i".
Если и a1, и a2 отсутствуют, подразумевается "i" "i".

Частичная (левая) векторизация бинарной операции.
bin_op: "!" "bin_op" 
Значение: a "!" "bin_op" b.
Аналогично векторизации, но в качестве второго аргумента
выступают не значения из b, а само значение b.

Частичная (правая) векторизация бинарной операции.
bin_op: "bin_op" "*"
Значение: a "bin_op" "*" b.
Аналогично векторизации, но в качестве первого аргумента
выступают не значения из a, а само значение a.

Векторизация унарной префиксной операции.
un_op: "un_op" "*"
Векторизация унарной постфиксной операции.
un_op: "!" "un_op" 

Примеры:

%{/2}* (a +<> b) // Среднее арифметическое для каждой пары элементов
(a +<> b) !/ 2 // аналогично предыдущему

(vec:*<16)!++ //Инкрементировать все элементы, меньшие 16.


stream :write* v // Записать в stream элементы v.

Исходная версия geekless, :

Я тут нашел описание грамматики выражений какого-то своего черновика ЯП, который набросал лет 5 назад. В общем, я просто оставлю это здесь. (Я не знаю, чем я упарывался.)

Приоритет и ассоциативность операций.

left             `
left             or
left             and
right            =, bin_op=
left             ? :?
left             ||
left             &&
left             |
left             ~
left             &
non-associative  ==, !=
non-associative  <, <=, >, >=
non-associative  in
left             shl, shr, rol, ror
left             +, -, 
left             *, /, -/
left             \r
right            \b, \rd
left             :...
left             :., операции объединения
left             ::, :*, операции поиска и выборки
left             as
right            !, ~(унарная), +(унарная), -(унарная), new, %..., <>...
right            ++ --
left             ^
left             ., ->, [], (), of


Простые операции.



Арифметические:
+(унарная) пустая операция
-(унарная) смена знака
+ сложение 
- вычитание
* умножение
/ деление
-/ взятие остатка
Для взятия остатка выбрана такая операция, поскольку -/ можно воспринимать
как сокращение a - a / b. По аналогии с конструкциями вида a += b логичнее
было бы /-, но это конфликтует с унарным минусом: a/-b.

Побитовые:
shr сдвиг вправо
shl сдвиг влево
ror вращение вправо
rol вращение влево
~   побитовое исключающее или
|   обитовое или
&   побитовое и
~(унарная) побитовое отрицание

Равенства:
== равно
!= не равно

Сравнения:
<  меньше
<= меньше или равно
>  больше
>= больше или равно

Логические:
&& логическое и
|| логическое или
!(унарная) логическое отрицание
and, or, not - аналогично, но с иным приоритетом.


Выборки:
:: выборка элемента из контейнера по ключу
:* выборка элементов из контейнера по ключам

vec::i // i-й элемент в vec, аналогично vec[i]
vec:*[1...10, 4] // выбрать с 1-го по 10-й, а затем 4-й (повторно)

Поиска и выборки:
Данные операции конструируются по следующему шаблону:
":" "!"? (">" | "<" | "*") ("<" | "<=" | ">" | ">=" | "!=" | "==" | "/")
Если имеется "!", результатом служит ключ(ключи) найденного
элемента(элементов), иначе - значение элемента.
Если далее идёт ">", поиск осуществляется от начала к концу,
если "<" - от конца к началу, если "*" - поиск осуществляется
по всему контейнеру и тип результата - контейнер с выбранными
элементами. Далее указывается либо:
1) либо одна из операций "<", "<=", ">", ">=", "!=", "==",
в этом случае осуществляется поиск элемента, для которого
данная операция истинна (при сравнении со вторым операндом),
2) либо символ "/", в этом случае второй операнд - функция-фильтр.
Примеры:
vec:!<==' ' // возвращает ключ элемента со значением ' ', поиск с конца
vec:>/filter // возвращает значение элемента, для которого filter вернул true, поиск с начала

vec:*/filter // выбрать все элементы, для которых функция filter вернула true


in имеется ли в контейнере (второй операнд) элемент, равный первому операнду

' ' in vec


Конкатенации:
:. конкатенация

vec = ['a', 'b', ' ', '0'];
vec:.['q', 'w'] // ['a', 'b', ' ', '0', 'q', 'w']


Объединения:
Данные операции конструируются по следующему шаблону:
":" операция_для_уникальных_ключей операция_для_неуникальных_ключей.
Два контейнера объединяются по ключам.
Ключи, которые имеются только в одном контейнере:
*  включать элементы из обоих контейнеров
1  включать элементы из левого контейнера
2  включать элементы из правого контейнера
0  не включать эти элементы
Ключи, которые имеются в обоих контейнерах:
1  включать значения элементов из левого контейнера
2  включать значения элементов из правого контейнера
== включить только совпадающие в обоих контейнерах значения
!= включить только не совпадающие в обоих контейнерах значения
>  включать большее значение
<  включать меньшее значение
0  не включать эти элементы
Примечание. Сочетания :11, :22, :00 разрешены. Результат, соотвественно,
левый контейнер, правый контейнер и пустой контейнер.

Примеры:
v1:0==v2 // найти пары ключ-значение, общие для обоих контейнеров
v1:20 v2 // найти пары элементы с уникальным ключём в правом контейнере


Приведения типа:
as - привести к указанному типу
a as integer // привести a к типу integer


Присваивания:
= присваивание



Выражения-операции.

Инверсия.
bin_op : "\" bin_op;
Значение: a "\" bin_op b === b bin_op a

Сложное присваивание.
bin_op : bin_op "=";
Значение: a bin_op "=" b === a "=" a bin_op b

Выбор.
bin_op : "??" bin_op;
Значение: a "??" bin_op b === a bin_op b "?" a ":" b

Примеры:
a ??> b // большее из a и b



Свёртка. (Reduce)
un_op : "\r" bin_op;
Значение: "\r" bin_op a === {if %len a == 0, raise Exc; auto i = %iterator a; __result = i++^; foreach auto v in i, __result bin_op= v;}

Свёртка со значением по умолчанию. (Reduce with Default)
bin_op : "\rd" bin_op;
Значение: b "\rd" bin_op a === {__result = b; auto i = %iterator a; foreach auto v in i, __result bin_op= v;}

Примеры:
\r+[1, 2, 3] // 1 + 2 + 3
5 \rd+[1, 2, 3] // 5 + 1 + 2 + 3
a\rd??>=vec; // Среди значения a и всех значений
контейнера vec выбрать максимальное при присвоить a.

Разветвление. (Branch)
un_op : "\b" un_op*(1) "{" bin_op "}" un_op*(2) ;
Значение: "\b" un_op*(1) "{" bin_op "}" un_op*(2) a === (un_op*(1) a) bin_op (un_op*(2) a)

Примеры:
\b\r+{/}%len v // (\r+ v) / (%len v); вычисление среднего арифметического элементов v

Понижение до унарной операции.
(Объединение последовательности бинарных операций в унарную.)
un_op : "%" "{" bin_op expression { "," bin_op expression}  "}" ;
Значение: "%" "{" bin_op expression { "," bin_op expression}  "}" a === алгоритм:
1) __result(0) = a;
2) для каждого i-го фрагмента вида bin_op expression,
__result(i) = __result(i-1) bin_op(i) expression(i);
Следует обратить внимание, что переменные __result(0),
__result(1), __result(2) и т.п. - это разные переменные, могущие иметь разные типы.


\b \r+%{:/filter1} {/} \r+%{:/filter2} v
// Выбирает из v элементы по фильтру filter1, ищет их сумму;
// выбирает из v элементы по фильтру filter2, ищет их сумму;
// находит частное от сумм.

Векторизация бинарной операции.
bin_op: "bin_op" "<" a1 a2 ">"
Значение: бинарная операция применяется к парам значений
(с совпадающими ключами) из двух контейнеров. Параметры a1 и a1
указывают, как поступать с элементами (соотвественно, в левом и
правом контейнере), которые не имеют пары:
"e" - иницировать исключение при встрече такого элемента
"i" - игнорировать такие элементы и не включать в контейнер-результат
"r" помещать такие элементы в контейнер результат без выполнения над ним вычислений
"{" expression "}" использовать в качестве пары
    значение expression (значение вычисляет один раз в начале
    выполнения векторизованной операции)
"!{" expression "}" использовать в качестве пары
    значение expression (значение вычисляет для каждой пары
    заново)
"l" использовать в качестве пары значение, свойства last
    другого контейнера
"f" использовать в качестве пары значение, свойства first
    другого контейнера
Если a2 отсуствует, подразумевается "i".
Если и a1, и a2 отсутствуют, подразумевается "i" "i".

Частичная (левая) векторизация бинарной операции.
bin_op: "!" "bin_op" 
Значение: a "!" "bin_op" b.
Аналогично векторизации, но в качестве второго аргумента
выступают не значения из b, а само значение b.

Частичная (правая) векторизация бинарной операции.
bin_op: "bin_op" "*"
Значение: a "bin_op" "*" b.
Аналогично векторизации, но в качестве первого аргумента
выступают не значения из a, а само значение a.

Векторизация унарной префиксной операции.
un_op: "un_op" "*"
Векторизация унарной постфиксной операции.
un_op: "!" "un_op" 

Примеры:

%{/2}* (a +<> b) // Среднее арифметическое для каждой пары элементов
(a +<> b) !/ 2 // аналогично предыдущему

(vec:*<16)!++ //Инкрементировать все элементы, меньшие 16.


stream :write* v // Записать в stream элементы v.