Skip to content

Commit 4a209dd

Browse files
committed
Add a new module to analyse categories
1 parent 9ac4db3 commit 4a209dd

File tree

1 file changed

+47
-0
lines changed
  • rascal-textmate-core/src/main/rascal/lang/rascal/grammar/analyze

1 file changed

+47
-0
lines changed
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
module lang::rascal::grammar::analyze::Categories
2+
3+
import Grammar;
4+
import ParseTree;
5+
6+
import lang::rascal::grammar::Util;
7+
8+
@synopsis{
9+
Special value to indicate that a production has no category
10+
}
11+
12+
public str NO_CATEGORY = "";
13+
14+
@synopsis{
15+
Gets a set of categories such that, for each category, there exists a string
16+
with that category produced by production `p`, as part of a string produced
17+
by a start production of grammar `g`
18+
}
19+
20+
set[str] getCategories(Grammar g, Production p)
21+
= getCategoriesByProduction(g)[p];
22+
23+
@memo
24+
private map[Production, set[str]] getCategoriesByProduction(Grammar g) {
25+
map[Production, set[str]] ret = (p: {} | /p: prod(_, _, _) := g);
26+
27+
void doGet(Production p, set[str] parentCategories) {
28+
set[str] categories = {c | /\tag("category"(str c)) := p};
29+
30+
set[str] old = ret[p];
31+
set[str] new = _ <- categories ? categories : old + parentCategories;
32+
ret[p] = new;
33+
34+
// If the new categories of `p` are different from the old ones, then
35+
// propagate these changes to the children of `p`
36+
for (old != new, /Symbol s := p.symbols, child <- lookup(g, delabel(s))) {
37+
doGet(child, new);
38+
}
39+
}
40+
41+
// Propagate categories from the roots of the grammar
42+
for (root: prod(\start(_), _, _) <- ret) {
43+
doGet(root, {NO_CATEGORY});
44+
}
45+
46+
return ret;
47+
}

0 commit comments

Comments
 (0)