- Вы можете заменить указанный c узел дерева разбора на себя посещением
=>
и заменить дочерние элементы обратно. В приведенном ниже примере заменяются только пробелы вокруг +
, затем - Вы можете заменить все макеты в одном go, посетив дерево и сопоставив его в нетерминальном макете (может быть другой название для вашей грамматики). В приведенном ниже примере вы также можете увидеть, как это делается.
module NormalizeLayout
import demo::lang::Pico::Syntax;
import ParseTree;
import IO;
// a stub space
private Layout space = appl(prod(layouts("Layout"), [], {}), [char(32)]);
void example() {
t = parse(#start[Program],
"begin
' declare
' a : natural;
'
' a := 1 +
' 1
'end");
t = visit (t) {
// this one sets the spaces only of a very specific rule, namely + expressions:
case (Expression) `<Expression l> + <Expression r>`
=> (Expression) `<Expression l> + <Expression r>`
// as an alternative here we match all layout in the entire program and replace it
case Layout _ => space
}
println(t); // begin declare a : natural ; a := 1 + 1 end
}
Основная трудность заключается в получении примера дерева разбора для пробела, начиная с обозначений (NT)
и [NT]
не поддерживает синтаксический анализ непосредственно из нетерминального макета. Поэтому в этом примере я перешел на общий уровень c и изобрел дерево разбора для Layouts (см. Модуль ParseTree
, чтобы узнать, как деревья разбора определяются внутри Rascal).
Другой (тип -безопасно) уловка для получения такого дерева примеров заключается в том, чтобы получить пример из следующего примера:
private Layout space() {
visit ((Expression) `1 + 1`) {
case Layout x : return x;
}
fail;
}