Skip to content

Commit dfd7f83

Browse files
committed
RGH: fix meta rule cardinality merge
1 parent da3e391 commit dfd7f83

File tree

3 files changed

+120
-6
lines changed

3 files changed

+120
-6
lines changed

src/org/intellij/grammar/generator/RuleGraphHelper.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,8 @@ else if (isPrivateOrNoType(metaRule)) {
443443
if (idx > -1 && idx < arguments.size()) {
444444
Map<PsiElement, Cardinality> argMap = collectMembers(rule, arguments.get(idx), visited);
445445
for (PsiElement element : argMap.keySet()) {
446-
result.put(element, cardinality.and(argMap.get(element)));
446+
Cardinality existing = ObjectUtils.notNull(result.get(element), NONE);
447+
result.put(element, existing.or(cardinality.and(argMap.get(element))));
447448
}
448449
}
449450
}

testData/generator/ExternalRules.bnf

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@
44
parserUtilClass="org.intellij.grammar.parser.GeneratedParserUtilBase"
55
tokens=[
66
perc='%'
7+
paren1='('
8+
paren2=')'
9+
comma=','
710
perc_re='regexp:\%'
811
]
912
}
1013

1114
// external parsing
1215
root ::= <<listOf statement>>
16+
external ref ::= parseRef
1317
external unique_list_of ::= uniqueListOf
1418
external unique_list_of_params ::= uniqueListOf <<p1>> "1+1" <<p2>> '1+1'
1519
external empty_external ::=
@@ -47,6 +51,10 @@ private multi_level ::= <<meta_multi_level one>>
4751
private meta_seq_of_lists_opt ::= (<<list_of_lists one (one | two)>>)?
4852
private meta_multi_level_no_closure ::= <<comma_list <<comma_list <<comma_list some>>>>>>
4953

54+
private meta comma_paren_list ::= '(' <<param>> (',' <<param>>) * ')' {pin=1}
55+
public_paren_list ::= <<comma_paren_list (ref | '(' one ')')>>
56+
public_paren_list2 ::= {elementType=public_paren_list}
57+
5058
// mixed
5159
private meta meta_mixed ::= <<listOf "1+2" '1+2' <<param>>>>
5260
private meta_mixed_simple ::= <<meta_mixed statement>>
@@ -82,6 +90,7 @@ private one_list_par ::= <<listOf (one)>>
8290
private meta second_class_meta ::= <<bmp>>
8391
private main_class_meta_usage_from_second ::= <<comma_list <<main_class_meta some>>>>
8492
private third_class_meta_usage_from_second ::= <<comma_list <<third_class_meta some>>>>
93+
extra_root ::= {extraRoot=true}
8594

8695
;{
8796
parserClass="ExternalRules3"

testData/generator/ExternalRules.expected.java

Lines changed: 109 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,22 @@ public void parseLight(IElementType root_, PsiBuilder builder_) {
2929
result_ = parse_root_(root_, builder_, 0);
3030
}
3131
else {
32-
result_ = false;
32+
result_ = parse_extra_roots_(root_, builder_, 0);
3333
}
3434
exit_section_(builder_, 0, marker_, root_, result_, true, TRUE_CONDITION);
3535
}
3636

37+
static boolean parse_extra_roots_(IElementType root_, PsiBuilder builder_, int level_) {
38+
boolean result_;
39+
if (root_ == EXTRA_ROOT) {
40+
result_ = ExternalRules2.extra_root(builder_, level_ + 1);
41+
}
42+
else {
43+
result_ = false;
44+
}
45+
return result_;
46+
}
47+
3748
protected boolean parse_root_(IElementType root_, PsiBuilder builder_, int level_) {
3849
return root(builder_, level_ + 1);
3950
}
@@ -96,7 +107,7 @@ private static boolean comma_list_1_0(PsiBuilder builder_, int level_, Parser pa
96107
if (!recursion_guard_(builder_, level_, "comma_list_1_0")) return false;
97108
boolean result_;
98109
Marker marker_ = enter_section_(builder_);
99-
result_ = consumeToken(builder_, ",");
110+
result_ = consumeToken(builder_, COMMA);
100111
result_ = result_ && param.parse(builder_, level_);
101112
exit_section_(builder_, marker_, null, result_);
102113
return result_;
@@ -143,15 +154,54 @@ private static boolean comma_list_pinned_2_0(PsiBuilder builder_, int level_, Pa
143154
// ',' <<param>>
144155
public static boolean comma_list_tail(PsiBuilder builder_, int level_, Parser param) {
145156
if (!recursion_guard_(builder_, level_, "comma_list_tail")) return false;
157+
if (!nextTokenIs(builder_, COMMA)) return false;
146158
boolean result_, pinned_;
147159
Marker marker_ = enter_section_(builder_, level_, _NONE_, COMMA_LIST_TAIL, null);
148-
result_ = consumeToken(builder_, ",");
160+
result_ = consumeToken(builder_, COMMA);
149161
pinned_ = result_; // pin = 1
150162
result_ = result_ && param.parse(builder_, level_);
151163
exit_section_(builder_, level_, marker_, result_, pinned_, null);
152164
return result_ || pinned_;
153165
}
154166

167+
/* ********************************************************** */
168+
// '(' <<param>> (',' <<param>>) * ')'
169+
static boolean comma_paren_list(PsiBuilder builder_, int level_, Parser param) {
170+
if (!recursion_guard_(builder_, level_, "comma_paren_list")) return false;
171+
if (!nextTokenIs(builder_, PAREN1)) return false;
172+
boolean result_, pinned_;
173+
Marker marker_ = enter_section_(builder_, level_, _NONE_);
174+
result_ = consumeToken(builder_, PAREN1);
175+
pinned_ = result_; // pin = 1
176+
result_ = result_ && report_error_(builder_, param.parse(builder_, level_));
177+
result_ = pinned_ && report_error_(builder_, comma_paren_list_2(builder_, level_ + 1, param)) && result_;
178+
result_ = pinned_ && consumeToken(builder_, PAREN2) && result_;
179+
exit_section_(builder_, level_, marker_, result_, pinned_, null);
180+
return result_ || pinned_;
181+
}
182+
183+
// (',' <<param>>) *
184+
private static boolean comma_paren_list_2(PsiBuilder builder_, int level_, Parser param) {
185+
if (!recursion_guard_(builder_, level_, "comma_paren_list_2")) return false;
186+
while (true) {
187+
int pos_ = current_position_(builder_);
188+
if (!comma_paren_list_2_0(builder_, level_ + 1, param)) break;
189+
if (!empty_element_parsed_guard_(builder_, "comma_paren_list_2", pos_)) break;
190+
}
191+
return true;
192+
}
193+
194+
// ',' <<param>>
195+
private static boolean comma_paren_list_2_0(PsiBuilder builder_, int level_, Parser param) {
196+
if (!recursion_guard_(builder_, level_, "comma_paren_list_2_0")) return false;
197+
boolean result_;
198+
Marker marker_ = enter_section_(builder_);
199+
result_ = consumeToken(builder_, COMMA);
200+
result_ = result_ && param.parse(builder_, level_);
201+
exit_section_(builder_, marker_, null, result_);
202+
return result_;
203+
}
204+
155205
/* ********************************************************** */
156206
// empty_external
157207
static boolean empty_external_usage(PsiBuilder builder_, int level_) {
@@ -180,9 +230,9 @@ private static boolean item_recover_0(PsiBuilder builder_, int level_) {
180230
if (!recursion_guard_(builder_, level_, "item_recover_0")) return false;
181231
boolean result_;
182232
Marker marker_ = enter_section_(builder_);
183-
result_ = consumeToken(builder_, ",");
233+
result_ = consumeToken(builder_, COMMA);
184234
if (!result_) result_ = consumeToken(builder_, ";");
185-
if (!result_) result_ = consumeToken(builder_, ")");
235+
if (!result_) result_ = consumeToken(builder_, PAREN2);
186236
exit_section_(builder_, marker_, null, result_);
187237
return result_;
188238
}
@@ -633,6 +683,48 @@ static boolean perc_re_list2(PsiBuilder builder_, int level_) {
633683
return listOf(builder_, level_ + 1, perc_re_list2_0_0_parser_);
634684
}
635685

686+
/* ********************************************************** */
687+
// <<comma_paren_list (ref | '(' one ')')>>
688+
public static boolean public_paren_list(PsiBuilder builder_, int level_) {
689+
if (!recursion_guard_(builder_, level_, "public_paren_list")) return false;
690+
if (!nextTokenIs(builder_, PAREN1)) return false;
691+
boolean result_;
692+
Marker marker_ = enter_section_(builder_);
693+
result_ = comma_paren_list(builder_, level_ + 1, public_paren_list_0_0_parser_);
694+
exit_section_(builder_, marker_, PUBLIC_PAREN_LIST, result_);
695+
return result_;
696+
}
697+
698+
// ref | '(' one ')'
699+
private static boolean public_paren_list_0_0(PsiBuilder builder_, int level_) {
700+
if (!recursion_guard_(builder_, level_, "public_paren_list_0_0")) return false;
701+
boolean result_;
702+
Marker marker_ = enter_section_(builder_);
703+
result_ = parseRef(builder_, level_ + 1);
704+
if (!result_) result_ = public_paren_list_0_0_1(builder_, level_ + 1);
705+
exit_section_(builder_, marker_, null, result_);
706+
return result_;
707+
}
708+
709+
// '(' one ')'
710+
private static boolean public_paren_list_0_0_1(PsiBuilder builder_, int level_) {
711+
if (!recursion_guard_(builder_, level_, "public_paren_list_0_0_1")) return false;
712+
boolean result_;
713+
Marker marker_ = enter_section_(builder_);
714+
result_ = consumeToken(builder_, PAREN1);
715+
result_ = result_ && one(builder_, level_ + 1);
716+
result_ = result_ && consumeToken(builder_, PAREN2);
717+
exit_section_(builder_, marker_, null, result_);
718+
return result_;
719+
}
720+
721+
/* ********************************************************** */
722+
public static boolean public_paren_list2(PsiBuilder builder_, int level_) {
723+
Marker marker_ = enter_section_(builder_);
724+
exit_section_(builder_, marker_, PUBLIC_PAREN_LIST, true);
725+
return true;
726+
}
727+
636728
/* ********************************************************** */
637729
// <<param>>
638730
static boolean recoverable_item(PsiBuilder builder_, int level_, Parser param) {
@@ -799,6 +891,11 @@ public boolean parse(PsiBuilder builder_, int level_) {
799891
}
800892
};
801893
static final Parser perc_re_list2_0_0_parser_ = PERC_RE_parser_;
894+
static final Parser public_paren_list_0_0_parser_ = new Parser() {
895+
public boolean parse(PsiBuilder builder_, int level_) {
896+
return public_paren_list_0_0(builder_, level_ + 1);
897+
}
898+
};
802899
static final Parser statement_parser_ = new Parser() {
803900
public boolean parse(PsiBuilder builder_, int level_) {
804901
return statement(builder_, level_ + 1);
@@ -828,6 +925,13 @@ public boolean parse(PsiBuilder builder_, int level_) {
828925
@SuppressWarnings({"SimplifiableIfStatement", "UnusedAssignment"})
829926
public class ExternalRules2 {
830927

928+
/* ********************************************************** */
929+
public static boolean extra_root(PsiBuilder builder_, int level_) {
930+
Marker marker_ = enter_section_(builder_);
931+
exit_section_(builder_, marker_, EXTRA_ROOT, true);
932+
return true;
933+
}
934+
831935
/* ********************************************************** */
832936
// <<comma_list <<main_class_meta some>>>>
833937
static boolean main_class_meta_usage_from_second(PsiBuilder builder_, int level_) {

0 commit comments

Comments
 (0)