in src/org/intellij/grammar/livePreview/LivePreviewParser.java [424:512]
private boolean generateExternalCall(PsiBuilder builder,
int level,
BnfRule rule,
List<BnfExpression> expressions,
String nextName,
Map<String, Parser> externalArguments) {
List<BnfExpression> callParameters = expressions;
List<String> metaParameterNames;
String method = expressions.size() > 0 ? expressions.get(0).getText() : null;
BnfRule targetRule = method == null ? null : myFile.getRule(method);
// handle external rule call: substitute and merge arguments from external expression and rule definition
if (targetRule != null) {
metaParameterNames = GrammarUtil.collectMetaParameters(targetRule, targetRule.getExpression());
if (Rule.isExternal(targetRule)) {
callParameters = GrammarUtil.getExternalRuleExpressions(targetRule);
method = callParameters.get(0).getText();
if (metaParameterNames.size() < expressions.size() - 1) {
callParameters = ContainerUtil.concat(callParameters, expressions.subList(metaParameterNames.size() + 1, expressions.size()));
}
if (myFile.getRule(method) == null) {
// not supported
return false;
}
}
}
else {
// Hard-coded extensions:
if ("eof".equals(method) && expressions.size() == 1) {
return eof(builder, level);
}
else if ("anything".equals(method) && expressions.size() == 2) {
BnfExpression finalNested = expressions.get(1);
parseAsTree(ErrorState.get(builder), builder, level + 1, DUMMY_BLOCK, true, TOKEN_ADVANCER,
(builder14, level14) -> generateNodeCall(builder14, level14, rule, finalNested, getNextName(nextName, 0), Collections.emptyMap()));
return true;
}
// not supported
return false;
}
if (callParameters.size() <= 1) {
return rule(builder, level, targetRule, externalArguments);
}
Map<String, Parser> argumentMap = new HashMap<>();
for (int i = 1, len = Math.min(callParameters.size(), metaParameterNames.size() + 1); i < len; i++) {
BnfExpression nested = callParameters.get(i);
String argument = nested.getText();
String argName = metaParameterNames.get(i - 1);
String argNextName;
int metaIdx;
if (argument.startsWith("<<") && (metaIdx = metaParameterNames.indexOf(argument)) > -1) {
nested = expressions.get(metaIdx + 1);
argNextName = getNextName(nextName, metaIdx);
}
else {
argNextName = getNextName(nextName, i - 1);
}
BnfExpression finalNested = nested;
if (nested instanceof BnfReferenceOrToken || nested instanceof BnfLiteralExpression) {
BnfRule argRule = nested instanceof BnfReferenceOrToken? myFile.getRule(nested.getText()) : null;
argumentMap.put(argName, (builder13, level13) -> {
if (argRule != null) {
return rule(builder13, level13, argRule, Collections.emptyMap());
}
else {
return generateNodeCall(builder13, level13, rule, finalNested, nextName, Collections.emptyMap());
}
});
}
else if (nested instanceof BnfExternalExpression) {
List<BnfExpression> expressionList = ((BnfExternalExpression)nested).getExpressionList();
boolean metaRule = Rule.isMeta(rule) || Rule.isExternal(rule);
if (metaRule && expressionList.size() == 1) {
// parameter
argumentMap.put(argName, externalArguments.get("<<" + expressionList.get(0).getText() + ">>"));
}
else {
argumentMap.put(argName, (builder12, level12) -> generateNodeCall(builder12, level12, targetRule, finalNested, argNextName, externalArguments));
}
}
else {
argumentMap.put(argName,
(builder1, level1) -> generateNodeCall(builder1, level1, targetRule, finalNested, argNextName, externalArguments));
}
}
if (Rule.isExternal(targetRule)) {
return generateExternalCall(builder, level, targetRule, callParameters, targetRule.getName(), argumentMap);
}
return rule(builder, level, targetRule, argumentMap);
}