Отчасти продолжение нерешенной задачи
topic95339.htmlИмеется такой язык, описанный неформально:
c-объект —
_c (любое выражение вида
c[...])
коэффициент — что угодно, что не содержит
_c, т.е.
x_ /; FreeQ[x, _c]H-член — произведение двух линейных комбинаций c-объектов
H-выражение — линейная комбинация H-членов
Предлагаю такую формальную грамматику:
Код:
c-obj ::= _c #
coeff ::= x_ /; FreeQ[x, _c] #
c-lin-term ::= c-obj | coeff * c-lin # слагаемое в линейной комбинации
c-lin ::= Plus[ c-lin-term .. ] # сама линейная комбинация c-объектов
H-term ::= c-lin * c-clin #
H-lin-term ::= H-term | coeff * H-expr # слагаемое в линейной комбинации H-термов
H-expr ::= Plus[ H-lin-term .. ] #
В 3-й и 6-й строчках вместо
coeff * c-obj и
coeff * H-term написаны более общие шаблоны
coeff * c-lin и
coeff * H-expr, чтобы выражения вида
a * (b * (c[1] + c[2]) + d * c[3]) были допустимыми для языки.
Интерпретация:
c-объект и коэффициенты интерпретируются как есть. По дистрибутивности все скобки должны быть раскрыты так, чтобы H-выражение было представлено в виде суммы слагаемых вида
coeff * c-объект * c-объект.
Дополнительные неформализованные требования: в ответе-результате стоит заменить стандартные
Plus и
Times на
List и
T, соответственно, и позволить некоторым H-членам исходного выражения быть записанными в таком виде.
(Как-то так для списка в качестве знака суммы)
Код:
c-obj ::= _c #
coeff ::= x_ /; FreeQ[x, _c] #
c-lin-term ::= c-obj | coeff * c-lin # слагаемое в линейной комбинации
c-lin ::= Plus[ c-lin-term .. ] # сама линейная комбинация c-объектов
H-term ::= c-lin * c-clin #
H-lin-term ::= H-term | coeff * H-expr # слагаемое в линейной комбинации H-термов
H-expr ::= Plus[ H-lin-term .. ] | List[ H-expr .. ] | Plus[ H-expr .. ]
Как такое реализовать по-проще в Wolfram Mathematica? 1) является ли введённое выражение допустимым для языка или нет по конкретной причине 2) унифицированный вид
Принципиальное решение я, конечно, вижу: для каждого понятия написать функцию, которая определяет, парсится ли выражение-аргумент, и другую функцию, сопоставляющую выражению его значение, — но оно имеющаяся реализация мне видится неоптимальной. Кстати, первый листинг может использоваться для парсинга выражения (правда, нужно контролировать, чтобы под .. понималось 2 и более членов, а коеффициент всегда был бы отличен от 1), второй же — нет из-за последней строчки, которая впадает в бесконечную рекурсию.
Как решаются такие задачи парсинга в WM?