You can label rule elements with name =
like this:
oC_RangeLiteral
: '*' SP?
( first=oC_IntegerLiteral SP? )?
( '..' SP? ( second=oC_IntegerLiteral SP? )? )?
;
Not sure how to use them with the C++ runtime, but for, say, Java, that'd look like this:
if (ctx.first != null) {
// 'first' exists
}
if (ctx.second != null) {
// 'second' exists
}
EDIT
Is it possible to achieve similar without modifying the grammar?
Sure, but that makes it a lot messier. You'd need to figure out if there is a ..
among the children of oC_RangeLiteral
and then check if the oC_IntegerLiteral
comes before or after this ..
token. Something like this:
// Only need to check if 1 child is present: in case of 2 or 0 children, it is clear
if (ctx.oC_IntegerLiteral().size() == 1) {
int indexOfIntegerLiteral = ctx.children.indexOf(ctx.oC_IntegerLiteral().get(0));
OptionalInt indexOfDotDot = java.util.stream.IntStream
.range(0, ctx.children.size())
.filter(i -> ctx.children.get(i).getText().equals(".."))
.findFirst();
System.out.printf("indexOfIntegerLiteral=%d\n", indexOfIntegerLiteral);
System.out.printf("indexOfDotDot=%s\n", indexOfDotDot);
if (indexOfDotDot.isPresent() && indexOfIntegerLiteral > indexOfDotDot.getAsInt()) {
// If there is a ".." and the single `oC_IntegerLiteral` comes after it: it's the second one
}
else {
// otherwise, it's the first `oC_IntegerLiteral`
}
}