in jflex/src/main/java/jflex/core/Macros.java [141:209]
private RegExp expandMacro(String name, RegExp definition) throws MacroException {
// Out.print("checking macro "+name);
// Out.print("definition is "+definition);
switch (definition.type) {
case sym.BAR:
case sym.CONCAT:
RegExp2 binary = (RegExp2) definition;
binary.r1 = expandMacro(name, binary.r1);
binary.r2 = expandMacro(name, binary.r2);
return definition;
case sym.STAR:
case sym.PLUS:
case sym.QUESTION:
case sym.BANG:
case sym.TILDE:
RegExp1 unary = (RegExp1) definition;
unary.content = expandMacro(name, (RegExp) unary.content);
return definition;
case sym.MACROUSE:
String usename = (String) ((RegExp1) definition).content;
if (Objects.equals(name, usename))
throw new MacroException(ErrorMessages.get(MACRO_CYCLE, name));
RegExp usedef = getDefinition(usename);
if (usedef == null) {
throw new MacroException(
ErrorMessages.get(ErrorMessages.MACRO_DEF_MISSING, usename, name));
}
markUsed(usename);
return expandMacro(name, usedef);
case sym.STRING:
case sym.STRING_I:
case sym.CHAR:
case sym.CHAR_I:
case sym.PRIMCLASS:
case sym.PRECLASS:
case sym.UNIPROPCCLASS:
return definition;
case sym.CCLASS:
case sym.CCLASSNOT:
RegExp1 cclass = (RegExp1) definition;
List<RegExp> classes = new ArrayList<>();
for (RegExp regexp : (List<RegExp>) cclass.content) {
classes.add(expandMacro(name, regexp));
}
cclass.content = classes;
return cclass;
case sym.CCLASSOP:
RegExp2 cclassOp = (RegExp2) ((RegExp1) definition).content;
cclassOp.r1 = expandMacro(name, cclassOp.r1);
cclassOp.r2 = expandMacro(name, cclassOp.r2);
return definition;
default:
throw new MacroException(
"unknown expression type " + definition.typeName() + " in macro expansion");
}
}