Вам не нужно построить узел на каждый сокращение, а узлы вы делаете строить не нужно включать каждый символ снижается. Также не нужно уменьшать символы в том же порядке, что и синтаксический анализ.
Во многих случаях AST является упрощением полного дерева синтаксического разбора, соответствующего вышеизложенному.
Простой пример, для грамматики выражения, используя Yacc-как генератор парсеров:
expr: term { $$ = $1; /* see below */ }
| expr '+' term { $$ = new_sum_node($1, $3); }
term: factor { $$ = $1; /* see below */ }
| term '*' factor { $$ = new_product_node($1, $3); }
factor: '(' expr ')' { $$ = $2; /* See below */ }
| ID { $$ = new_variable_node($1); }
| NUMBER { $$ = new_literal_node($1); }
АСТ построен в качестве смыслового значения не-терминалов. Ожидается, что функции new_*_node
возвратят вновь выделенный узел указанного типа. (Здесь мы предполагаем, что существует некоторый механизм вывода из указателя, какой тип узла он есть. Например, можно было бы использовать подтипирование и виртуальные функции.)
В Yacc (и аналогичных синтаксических анализаторах) каждый символ (терминальный или нетерминальный) имеет ассоциированное «значение», и каждое производство имеет связанное с ним действие, которое выполняется, когда производство уменьшается. Действие для производства может присваивать значение «значение» нетерминала. Действие может использовать «значения» компонентов правой стороны, поскольку каждый из них либо является терминалом (значение которого задано сканером), либо не-терминал, который уже был уменьшен. По сути, это S-attributed grammar.
Некоторые из приведенных выше сокращений вообще не проявляются в AST. В частности, сокращения единиц (expr:term
и term:factor
) просто проходят через AST для правой стороны. Точно так же сокращение скобок term:'(' expr ')'
просто проходит через AST для expr
, в результате чего скобки эффективно исчезают из AST. (Это неверно на всех языках, на некоторых языках, по-видимому, избыточные круглые скобки действительно влияют на семантику, и вам нужно создать узел AST для записи факта.)
В Yacc, $$ = $1
является действием уменьшения по умолчанию, если никаких действий не указано, и поскольку большинство сокращений единиц исключено из AST, они обычно отображаются без действий сокращения. Я сделал их явным для дидактических целей; на практике вы не должны этого делать.
Не возражаете, если я попрошу вас уточнить прохождение и действие по умолчанию. Также я не знаком с нотой $$. Это просто представление переменной? Извините, если это глупый вопрос, по какой-то причине мой разум просто с трудом справляется с этой конкретной проблемой. Но спасибо за ответ! –
@devin: извините, я принимал генератор синтаксиса yacc-like, я должен был быть более явным. В yacc установка $$ устанавливает «значение» уменьшенного нетерминала. «Значения» s правых символов стороны составляют $ 1, $ 2 и т. Д. – rici
@DevinWall: Надеюсь, что дополнительное объяснение несколько помогает. – rici