Сначала получите грамматику для вашего синтаксиса следующим образом:
import Grammar;
gr = grammar(#YourTopNonterminal);
Затем вы можете использовать этот библиотечный модуль (с примером кода для извлечения зависимостей):
import analysis::grammars::Dependency;
deps = symbolDependencies(gr);
Ивы получите бинарное отношение между зависимыми символами, например:
rascal>symbolDependencies(g)
Graph[Symbol]: {
<sort("A"),sort("B")>,
<sort("B"),sort("C")>
}
Основной код для symbolDependencies
таков:
Graph[Symbol] symbolDependencies(Grammar g) =
{ <from,to> | /prod(Symbol from,[_*,Symbol elem,_*],_) := g, /Symbol to := elem}
Понимание проходит по всем правиламграмматики, берет голову from
, а затем находит все символы to
в правиле (возможно, вложенные из-за регулярных выражений) и создает кортеж для каждой пары.
После этого вы 'я начал анализировать и преобразовывать это отношение, чтобы получить сильно связанные компоненты.Библиотечный модуль analysis::graphs::Graph
имеет пример функции, которая вычисляет подключенные компоненты (не сильно подключенных компонентов, поэтому вам придется адаптировать это).
rascal>import analysis::graphs::Graph;
ok
rascal>connectedComponents(symbolDependencies(g))
set[set[Symbol]]: {{
sort("A"),
sort("C"),
sort("B")
}}
Наконец, чтобы напечататьТакой символ, как sort("A")
, возвращающийся к хорошему имени, может пригодиться, особенно если у вас есть регулярные выражения над нетерминалами (например, * и +):
rascal>t = type(sort("A"),());
type[value]: type(
sort("A"),
())
rascal>"<t>"
str: "A"
Я бы также рекомендовал визуализировать графики, используяviz::Figure