Мы создаем очень простой язык программирования, используя Flex и Bison для анализа синтаксиса и синтаксиса, а также с помощью C для создания компилятора. Прежде чем перейти к сборке, мы создаем абстрактное синтаксическое дерево из языковых правил. Но у нас возникают проблемы с представлением одной конкретной функции с языка. функция описывается следующим образом:Абстрактное синтаксическое дерево в компиляторе: как точно представлять функцию?
FILTERC: Он принимает условие и список выражений в качестве входных данных и возвращает сколько из этих выражений соответствует условию. Это может быть одиночное или компромиссное условие. Используется в этой форме: FILTERC (условие, [список выражений]) Условие должно иметь знак подчеркивания перед каждым элементом, представляющий, где выражения должны быть помещены для сравнения. Пример: FILTERC (_> 4 и _ < = 6,5, [а + с, Ь, ча, д])
Это, как функция "filterc" выражается в правилах BNF (мы на самом деле использовали лексемы с Flex, но я упростил его с реальными персонажами, так что это не точка, а анализ синтаксиса правильно сделано Bison):
filter ::= FILTERC (condition_filter , [ expression_list ])
;
condition_filter ::= comparison_filter | comparison_filter AND comparison_filter | comparison_filter OR comparison_filter
;
comparison_filter ::= _ > expression | _ < expression | _ == expression | _ >= expression | _ <= expression | _ != expression
;
expression_list ::= expression | expression , expression_list
;
expression: term | expression + term | expression - term
;
term: factor | term * factor | term/factor
;
factor: ID | INT_LITERAL | REAL_LITERAL | STRING_LITERAL | (expression) | filter
;
Теперь мы должны написать функции, которые создают узлы абстрактного синтаксического дерева , На низком уровне функция «filterc» - это не что иное, как куча «IF», чтобы убедиться, что каждое из выражений соответствует условию, только теперь выражения будут помещены там, где подчеркивается. Таким образом, это было бы примерно так: (выражение) (оператор сравнения) (условие)
Дело в том, что фактическое предложение FILTERC считывается «назад»: сначала выражения считываются, а затем сравниваются с условием. Но программа читается последовательно: подчеркивание читается до того, как будет найдено фактическое выражение. Поэтому мы действительно запутались в том, как построить дерево.
Я не собираюсь добавлять весь код, который мы используем для создания узлов и листьев дерева, или это было бы полным беспорядком. Но в основном есть функция, которая создает узлы с двумя дочерними элементами (слева и справа), и когда не должно быть никаких детей, эти указатели имеют значение null. Основная структура, которую мы используем, заключается в том, чтобы поместить оператора в корневой узел и операнды в качестве дочерних элементов (например: в предложении «if» ключевым словом «if» должен быть корень, условием будет левый ребенок и код блок для выполнения, если true будет правильным потомком). Например:
IF condition THEN block {thenPtr = blockPtr;} ENDIF {createNode("if", conditionPtr, thenPtr);}
(«условие» и «блок» определены в другом месте, где создаются их указатели).
Мы смогли успешно создать дерево для выражения regex и для всех других правил на этом языке, но эта функция «фильтр» действительно запутанна.
Почему вас беспокоит порядок, в котором построены (под) AST деревья? Ваша проблема в анализе с АСТ заключается в том, чтобы зафиксировать то, что было проанализировано. Цель АСТ - результат захвата; его можно обработать позже в любом порядке (в отличие от синтаксического анализа, который слева направо). Итак ... создайте свои узлы AST для условия фильтра (вы четко знаете, как это сделать, присоединяя действия к правилам) и создайте свои узлы AST для выражений (путем присоединения действий к правилам), а затем запустите полученный парсер. Это должно привести к полному АСТ с условием и выражением фильтра. –
Спасибо, Ира. Но я до сих пор этого не понимаю: когда синтаксический анализатор читает правило 'filter :: = FILTERC (condition_filter, [expression_list])', он будет идти последовательно, поэтому он попытается определить, что такое 'condition_filter'. Он увидит, что condition_filter может быть compare_filter, и это может быть, например: 'compare_filter :: = _> выражение'. Поэтому ему необходимо создать узел с оператором (в данном случае, символ>), а слева и справа - с выражениями для сравнения. Проблема в том, что он еще не имеет левого выражения, потому что он его не читал. – Floella
Вы должны изменить название своего вопроса на нечто более похожее: «.. как построить дерево с помощью Bison?» –