Нужен способ разбора алгебраических выражений в C

Мне нужно разобрать алгебраические выражения для приложения, над которым я работаю, и я надеюсь получить немного коллективной мудрости, прежде чем взяться за дело и, возможно, пойти по ложному пути.

То, что мне нужно сделать, довольно прямолинейно: с учетом текстового алгебраического выражения (3 * x - 4 (y - sin (pi))) создать объектное представление уравнения. Пользовательские объекты уже существуют, поэтому мне нужен синтаксический анализатор, который создает дерево, по которому я могу пройти, чтобы создать экземпляры нужных мне объектов.

Основными требованиями будут:

  1. Способность выражать алгебру в виде грамматики, чтобы у меня был контроль и я мог настроить/расширить ее по мере необходимости.

  2. Исходный синтаксис будет включать целые числа, действительные числа, константы, переменные, арифметические операторы (+, -, *, /), степени (^), уравнения (=), круглые скобки, приоритет и простые функции (sin(pi)). Я надеюсь довольно быстро расширить свое приложение, чтобы оно поддерживало правильные функции (f(x) = 3x +2).

  3. Должен компилироваться на C, так как его нужно интегрировать в мой код.

Мне НЕ нужно вычислять выражение математически, поэтому программное обеспечение, которое вычисляет переменную или выполняет арифметические действия, является шумом.

Я сделал домашнюю работу в Google, и похоже, что лучший подход — использовать грамматику BNF и программное обеспечение для создания компилятора на C. Итак, мои вопросы:

  1. Существует ли уже BNF-грамматика с соответствующим генератором парсеров для алгебраических выражений (или, что еще лучше, LaTex)? Кто-то уже должен был это сделать. Я НА САМОМ ДЕЛЕ хочу не запускать свой собственный, главным образом потому, что не хочу его тестировать. Я был бы готов заплатить разумную сумму за библиотеку (менее 50 долларов)

  2. Если нет, то какой генератор синтаксических анализаторов для C, по вашему мнению, проще всего изучить/использовать здесь? Лекс? YACC? Flex, Bison, Python/SymPy, другие? Я не знаком ни с одним из них.


person David    schedule 09.01.2011    source источник
comment
В качестве альтернативы Lexx/Yacc вы можете попробовать алгоритм Дейкстры Shunting Yard: en.wikipedia.org/ wiki/Shunting-yard_algorithm Эта статья в Википедии содержит пример на C.   -  person Doc Brown    schedule 10.01.2011
comment
Я нашел то, что мне было нужно здесь: http://www.codeproject.com/KB/recipes/sota_expression_evaluator.aspx Спасибо всем за содержательные отзывы! -Дэйвид   -  person David    schedule 14.01.2011
comment
На самом деле, это оказалось намного полезнее, поскольку демонстрирует, как построить дерево: cs.man.ac.uk/~pjj/cs211/ho/node8.html   -  person David    schedule 07.06.2011
comment
При включении ссылок на внешние источники в свой ответ всегда обязательно включайте важные части из этого источника вместе с вашим ответом, так как ссылки могут со временем исчезнуть.   -  person Lukas Knuth    schedule 24.04.2013


Ответы (4)


Мне очень повезло с ANTLR. Он имеет среды выполнения для многих различных языков, включая C, и имеет очень удобный синтаксис для определения грамматик и построения деревьев. Я недавно написал похожую грамматику (алгебраические выражения) в 131 строку, что определенно управляемо.

person cdhowie    schedule 09.01.2011
comment
Сегодня я провел некоторое время, глядя на ANTLR. Удалось ли вам обойти взаимно леворекурсивные проблемы для вложенных уравнений? Например. знаменатель дроби сам может быть комплексным членом (4/(c*((1+1)/2)) и т. д. - person David; 10.01.2011
comment
Парсер, который у меня есть, на самом деле отлично разобрал бы это выражение. По сути, на верхнем уровне у вас есть операторы с самым низким приоритетом, а затем вы переходите к созданию атома, который может быть числом, идентификатором или выражением в скобках. Поскольку знаменатель дроби с числителем 4 открывается скобкой слева, двусмысленности нет. - person cdhowie; 10.01.2011

Стандартные инструменты Linux flex и bison, вероятно, были бы здесь наиболее подходящими. IIRC примеры синтаксических анализаторов и лексеров, используемых в этих инструментах, делают что-то близкое к тому, что вы хотите, поэтому вы можете просто изменить этот код, чтобы получить то, что вам нужно.

Эти инструменты выглядят так, как будто они соответствуют вашим требованиям. Вы можете настроить грамматику, скомпилировать до C и использовать любой оператор, какой захотите.

person templatetypedef    schedule 09.01.2011

Я использовал код (найденный в сети) из следующего:

Основы перевода программ» Питера Калингарта

Я улучшил его для обработки функций, что позволяет вам реализовывать такие вещи, как «if (a, b, c)» (вроде того, как это делает Excel).

person davep    schedule 09.01.2011

вы можете создать простой парсер самостоятельно или использовать любой из популярных "компилятор-компилятор" (некоторые из они были перечислены другими постами). просто решите, будет ли ваш парсер достаточно сложным, чтобы использовать (и изучать) внешний инструмент. в любом случае вам нужно будет определить грамматику, обычно это самая трудоемкая задача, если у вас нет предыдущего опыта. формальным способом определения синтаксических грамматик является BNF или EBNF

person Andriy Tylychko    schedule 09.01.2011