📄 fmparser.jj
字号:
}
FallbackInstruction result = new FallbackInstruction();
result.setLocation(template, tok, tok);
return result;
}
}
/**
* Production used to break out of a loop or a switch block.
*/
BreakInstruction Break() :
{
Token start;
}
{
start=<BREAK>
{
if (loopNesting < 1 && switchNesting <1)
{
String msg = getErrorStart(start) + "\n"
+ start.image
+ " occurred outside a loop or a switch block.";
throw new ParseException(msg, start.beginLine, start.beginColumn);
}
BreakInstruction result = new BreakInstruction();
result.setLocation(template, start, start);
return result;
}
}
/**
* Production used to jump out of a macro.
* The stop instruction terminates the rendering of the template.
*/
ReturnInstruction Return() :
{
Token start, end=null;
Expression exp = null;
}
{
(
start=<SIMPLE_RETURN>{end = start;}
|
start=<RETURN> exp=Expression() end=LooseDirectiveEnd()
)
{
if (inMacro) {
if (exp != null) {
String msg = getErrorStart(start)
+ "\nA macro cannot return a value";
throw new ParseException(msg, start.beginLine, start.beginColumn);
}
}
else if (inFunction) {
if (exp == null) {
String msg = getErrorStart(start)
+ "\nA function must return a value";
throw new ParseException(msg, start.beginLine, start.beginColumn);
}
}
else {
if (exp == null) {
String msg = getErrorStart(start)
+ "\nA return instruction can only occur inside a macro of function";
throw new ParseException(msg, start.beginLine, start.beginColumn);
}
}
ReturnInstruction result = new ReturnInstruction(exp);
result.setLocation(template, start, end);
return result;
}
}
StopInstruction Stop() :
{
Token start = null;
Expression exp = null;
}
{
(
start=<HALT>
|
start=<STOP> exp=Expression() LooseDirectiveEnd()
)
{
StopInstruction result = new StopInstruction(exp);
result.setLocation(template, start, start);
return result;
}
}
TemplateElement Nested() :
{
Token t, end;
ArrayList bodyParameters;
BodyInstruction result = null;
}
{
(
(
t=<SIMPLE_NESTED>
{
result = new BodyInstruction(null);
result.setLocation(template, t, t);
}
)
|
(
t=<NESTED>
bodyParameters=PositionalArgs()
end=LooseDirectiveEnd()
{
result = new BodyInstruction(bodyParameters);
result.setLocation(template, t, end);
}
)
)
{
if (!inMacro) {
throw new ParseException(getErrorStart(t)
+ "\nCannot use a "
+ t.image
+ " instruction outside a macro.",
t.beginLine, t.beginColumn);
}
return result;
}
}
TemplateElement Flush() :
{
Token t;
}
{
t=<FLUSH>
{
FlushInstruction result = new FlushInstruction();
result.setLocation(template, t, t);
return result;
}
}
TemplateElement Trim() :
{
Token t;
TrimInstruction result=null;
}
{
(
t=<TRIM> {result = new TrimInstruction(true, true);}
|
t=<LTRIM> {result = new TrimInstruction(true, false);}
|
t=<RTRIM> {result = new TrimInstruction(false, true);}
|
t=<NOTRIM> {result = new TrimInstruction(false, false);}
)
{
result.setLocation(template, t, t);
return result;
}
}
TemplateElement Assign() :
{
Token start, end;
int scope;
Token id=null;
Expression nameExp, exp, nsExp=null;
String varName;
ArrayList assignments = new ArrayList();
Assignment ass;
TemplateElement block;
}
{
(
start=<ASSIGN> {scope = Assignment.NAMESPACE;}
|
start=<GLOBALASSIGN>{scope = Assignment.GLOBAL;}
|
start=<LOCALASSIGN> {scope = Assignment.LOCAL;}
{
scope = Assignment.LOCAL;
if (!inMacro && !inFunction) {
String msg = getErrorStart(start)
+ "\nLocal variable assigned outside a macro.";
throw new ParseException(msg, start.beginLine, start.beginColumn);
}
}
)
nameExp=IdentifierOrStringLiteral()
{
varName = (nameExp instanceof StringLiteral) ? ((StringLiteral) nameExp).getAsString() : nameExp.toString();
}
((
<EQUALS>
exp=Expression()
{
ass = new Assignment(varName, exp, scope);
ass.setLocation(template, nameExp, exp);
assignments.add(ass);
}
(
LOOKAHEAD([<COMMA>](<ID>|<STRING_LITERAL>)<EQUALS>)
[<COMMA>]
nameExp=IdentifierOrStringLiteral()
{
varName = (nameExp instanceof StringLiteral) ? ((StringLiteral) nameExp).getAsString() : nameExp.toString();
}
<EQUALS>
exp=Expression()
{
ass = new Assignment(varName, exp, scope);
ass.setLocation(template, nameExp, exp);
assignments.add(ass);
}
)*
[
id=<IN>
nsExp=Expression() {if (scope != Assignment.NAMESPACE) throw new ParseException(getErrorStart(id) + "\nCannot assign to namespace here.", id.beginLine, id.beginColumn);}
]
end=LooseDirectiveEnd()
{
AssignmentInstruction ai = new AssignmentInstruction(scope);
for (int i = 0; i< assignments.size(); i++) {
ai.addAssignment((Assignment) assignments.get(i));
}
ai.setNamespaceExp(nsExp);
ai.setLocation(template, start, end);
return ai;
}
)
|
(
[
id=<IN>
nsExp=Expression() {if (scope != Assignment.NAMESPACE) throw new ParseException(getErrorStart(id) + "\nCannot assign to namespace here.", id.beginLine, id.beginColumn);}
]
<DIRECTIVE_END>
block=OptionalBlock()
(
end=<END_LOCAL> {if (scope != Assignment.LOCAL) throw new ParseException(getErrorStart(end) + "\nMismatched assignment tags.", end.beginLine, end.beginColumn);}
|
end=<END_ASSIGN> {if (scope != Assignment.NAMESPACE) throw new ParseException(getErrorStart(end) + "\nMismatched assignment tags.", end.beginLine, end.beginColumn);}
|
end=<END_GLOBAL> {if (scope != Assignment.GLOBAL) throw new ParseException(getErrorStart(end) + "\nMismatched assignment tags", end.beginLine, end.beginColumn);}
)
{
BlockAssignment ba = new BlockAssignment(block, varName, scope, nsExp);
ba.setLocation(template, start, end);
return ba;
}
))
}
Include Include() :
{
Expression nameExp;
Token att, start, end;
Expression exp, parseExp = null, encodingExp = null;
}
{
start=<INCLUDE>
nameExp=Expression()
[<SEMICOLON>]
(
att=<ID>
<EQUALS>
exp=Expression()
{
String attString = att.image;
if (attString.equalsIgnoreCase("parse")) {
parseExp = exp;
}
else if (attString.equalsIgnoreCase("encoding")) {
encodingExp = exp;
}
else {
String msg = getErrorStart(att)
+ "\nexpecting parse= or encoding= to be specified.";
throw new ParseException(msg, att.beginLine, att.beginColumn);
}
}
)*
end=LooseDirectiveEnd()
{
Include result = new Include(template, nameExp, encodingExp, parseExp);
result.setLocation(template, start, end);
return result;
}
}
LibraryLoad Import() :
{
Token start, end, ns;
Expression nameExp;
}
{
start=<IMPORT>
nameExp=Expression()
<AS>
ns=<ID>
end=LooseDirectiveEnd()
{
LibraryLoad result = new LibraryLoad(template, nameExp, ns.image);
result.setLocation(template, start, end);
template.addImport(result);
return result;
}
}
Macro Macro() :
{
Token arg, start, end;
Expression nameExp;
String name;
ArrayList argNames = new ArrayList();
HashMap args = new HashMap();
ArrayList defNames = new ArrayList();
Expression defValue=null;
TemplateElement block;
boolean isFunction = false, hasDefaults=false;
boolean isCatchAll = false;
String catchAll = null;
}
{
(
start=<MACRO>
|
start=<FUNCTION> {isFunction = true;}
)
{
if (inMacro || inFunction) {
throw new ParseException(getErrorStart(start)
+ "\nMacros cannot be nested.", start.beginLine, start.endLine);
}
if (isFunction) inFunction = true; else inMacro = true;
}
nameExp=IdentifierOrStringLiteral()
{
name = (nameExp instanceof StringLiteral) ? ((StringLiteral) nameExp).getAsString() : nameExp.toString();
}
[<OPEN_PAREN>]
(
arg=<ID> {defValue = null;}
[<ELLIPSIS> { isCatchAll = true; }]
[
<EQUALS>
defValue=Expression()
{
defNames.add(arg.image);
hasDefaults = true;
}
]
[<COMMA>]
{
if (catchAll != null) {
throw new ParseException(getErrorStart(arg)
+ "\nThere may only be one \"catch-all\" parameter in a macro declaration, "
+ "and it must be the last parameter.", arg.beginLine, arg.endLine);
}
if (isCatchAll) {
if (defValue != null) {
throw new ParseException(getErrorStart(arg)
+ "\n\"Catch-all\" macro parameter may not have a default value.",
arg.beginLine, arg.endLine);
}
catchAll = arg.image;
} else {
argNames.add(arg.image);
if (hasDefaults && defValue == null) {
throw new ParseException(getErrorStart(arg)
+ "\nIn a macro declaration, parameters without a default value "
+ "must all occur before the parameters with default values.",
arg.beginLine, arg.endLine);
}
args.put(arg.image, defValue);
}
}
)*
[<CLOSE_PAREN>]
<DIRECTIVE_END>
block=OptionalBlock()
(
end=<END_MACRO> { if(isFunction) throw new ParseException(getErrorStart(start) + "\nExpected function end tag here.", start.beginLine, start.endLine); }
|
end=<END_FUNCTION> { if(!isFunction) throw new ParseException(getErrorStart(start) + "\nExpected macro end tag here.", start.beginLine, start.endLine); }
)
{
inMacro = inFunction = false;
Macro result = new Macro(name, argNames, args, block);
result.setCatchAll(catchAll);
result.isFunction = isFunction;
result.setLocation(template, start, end);
template.addMacro(result);
return result;
}
}
CompressedBlock Compress() :
{
TemplateElement block;
Token start, end;
}
{
start=<COMPRESS>
block=OptionalBlock()
end=<END_COMPRESS>
{
CompressedBlock cb = new CompressedBlock(block);
cb.setLocation(template, start, end);
return cb;
}
}
TemplateElement UnifiedMacroTransform() :
{
Token start=null, end, t;
HashMap namedArgs = null;
ArrayList positionalArgs = null, bodyParameters = null;
String directiveName = null;
TemplateElement nestedBlock = null;
Expression exp;
}
{
start=<UNIFIED_CALL>
exp=Expression()
{
if (exp instanceof Identifier || (exp instanceof Dot && ((Dot) exp).onlyHasIdentifiers())) {
directiveName = exp.getCanonicalForm();
}
}
[<TERMINATING_WHITESPACE>]
(
LOOKAHEAD(<ID><EQUALS>)
namedArgs = NamedArgs()
|
positionalArgs=PositionalArgs()
)
[
<SEMICOLON>{bodyParameters = new ArrayList();}
[
t=<ID> {bodyParameters.add(t.image);}
(
<COMMA>
t = <ID>{bodyParameters.add(t.image);}
)*
]
]
(
end=<EMPTY_DIRECTIVE_END>
|
(
<DIRECTIVE_END>
nestedBlock=OptionalBlock()
end=<UNIFIED_CALL_END>
{
String s = end.image.substring(3);
s = s.substring(0, s.length() -1).trim();
if (s.length() >0 && !s.equals(directiveName)) {
String msg = getErrorStart(end);
if (directiveName == null) {
throw new ParseException(msg + "\nExpecting </@>", end.beginLine, end.beginColumn);
}
else {
throw new ParseException(msg + "\nExpecting </@> or </@" + directiveName + ">", end.beginLine, end.beginColumn);
}
}
}
)
)
{
TemplateElement result = (positional
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -