options { //Case sensitivity is required for JSP/PHP keyword "switch". //Don't change Java unicode escapes. //JAVA_UNICODE_ESCAPE=true; //If Unicode input is used, fix Run.main() to use relevant another XXCharStream. UNICODE_INPUT=false; STATIC=true; //COMMON_TOKEN_ACTION=true; //=> void CommonTokenAction(Token t) CACHE_TOKENS=true; //=> for files / whole packets only - OK OPTIMIZE_TOKEN_MANAGER=true; //DEBUG_PARSER=true; -not useful //SANITY_CHECK default true OTHER_AMBIGUITY_CHECK=5; CHOICE_AMBIGUITY_CHECK=100000; FORCE_LA_CHECK=true; //maybe not recomended? //DEBUG_TOKEN_MANAGER=true; } PARSER_BEGIN(Parser) package org.paneris.spindent; public final class Parser { } PARSER_END(Parser) <*> SPECIAL_TOKEN : { <#NO_WS: ~[" ", "\t", "\f", "\n", "\r"] > | <#NO_QWS: ~[" ", "\t", "\f", "\n", "\r", "'", "\""] > //No whitespace neither quotation mark/apostrophe | <#NO_TWS: ~[" ", "\t", "\f", "\n", "\r", "<"] > //No whitespace neither "<" tag opener | <#NO_TEQWS: ~[" ", "\t", "\f", "\n", "\r", ">", "'", "\""] > //No whitespace, ">" tag end, quotation/apostrophe | <#NO_CR: ~["\n", "\r"] > | <#IS_WS: ( [" ", "\t", "\f"] )+ > | <#IS_CR: ( ["\n", "\r"] )+ (["\n", "\r"] | )* > } //List of all token manager states: //DEFAULT, HTML_COMMENT, HTML_TAG, QUOTATION, APOSTROPHE, JAVASCRIPT, CODE, SINGLE_LINE_COMMENT, MULTILINE_COMMENT, PRE, SSI //Fix if states are changed => all modes except SINGLE_LINE_COMMENT, MULTI_LINE_COMMENT, PRE, SSI: SPECIAL_TOKEN: { > } //Empty new lines don't get indentation spaces added //Fix if states are changed => all modes except SINGLE_LINE_COMMENT, MULTI_LINE_COMMENT, PRE, SSI, QUOTATION, APOSTROPHE: SPECIAL_TOKEN: { > } //Multiple whitespaces inside text are easily replaced by 1 space // DEFAULT state is html // Token naming convention: // H_xxx = HTML token XXX // H_C_BEG = HTML token that starts CODE state // C_H_END = CODE token that ends and returns to HTML state SPECIAL_TOKEN [IGNORE_CASE]: { :HTML_COMMENT | :HTML_TAG | :HTML_TAG | > | :HTML_TAG | :HTML_TAG //for lower/uppercase transformation | "] )* ">" > :JAVASCRIPT | {Engine.pushPrevState(curLexState);} :CODE | "] )* ">" > :PRE | )* "#" > {Engine.pushPrevState(curLexState);} :SSI } SPECIAL_TOKEN: { // <% and as well. " > :DEFAULT | > }
 SPECIAL_TOKEN: {
	
|  :DEFAULT
|  {Engine.pushPrevState(curLexState);} :CODE
| )* "#" > {Engine.pushPrevState(curLexState);} :SSI
}

 SPECIAL_TOKEN: {
	
| " > {SwitchTo(Engine.popPrevState());}
}

 SPECIAL_TOKEN: {
	// 
   {Engine.pushPrevState(curLexState);} :QUOTATION
|  {Engine.pushPrevState(curLexState);} :APOSTROPHE
| " > :DEFAULT
| " > :DEFAULT
|  {Engine.pushPrevState(curLexState);} :CODE
|  >
| )* "#" > {Engine.pushPrevState(curLexState);} :SSI
}

//Multiline QUOTATION/APOSTROPHE don't work for Java, thus not supported. So successive lines will be indented.
//Should there be a need, exempt  from QUOTATION/APOSTROPHE states and manage Engine.indent(tok) and unindentSpaces.
 SPECIAL_TOKEN: {
	 {SwitchTo(Engine.popPrevState());}
|  {Engine.pushPrevState(curLexState);} :CODE
| 
| )* "#" > {Engine.pushPrevState(curLexState);} :SSI
}

 SPECIAL_TOKEN: {
	 {SwitchTo(Engine.popPrevState());}
|  {Engine.pushPrevState(curLexState);} :CODE
| 
| )* "#" > {Engine.pushPrevState(curLexState);} :SSI
}

 SPECIAL_TOKEN [IGNORE_CASE]: {
   {Engine.pushPrevState(curLexState);} :QUOTATION
|  {Engine.pushPrevState(curLexState);} :APOSTROPHE
| 
| 
| 
| 
|  {Engine.pushPrevState(curLexState);} :CODE
|  >
|  {Engine.pushPrevState(curLexState);} :SINGLE_LINE_COMMENT
|  {Engine.pushPrevState(curLexState);} :MULTI_LINE_COMMENT
| "] )* ">" > :DEFAULT //Enclosing ">" can be left for DEFAULT if DEFAULT is fine with that.
| )* "#" > {Engine.pushPrevState(curLexState);} :SSI
}

 SPECIAL_TOKEN [IGNORE_CASE]: {
	
|  | )+ "IF") | "NEXT" | "WEND" | ("END" ( | )+ "SUB") >
}

 SPECIAL_TOKEN: { 
	 {Engine.pushPrevState(curLexState);} :QUOTATION
|  {Engine.pushPrevState(curLexState);} :APOSTROPHE
| 
| 
| 
| 
| 
|  >
| " | "?>" > {SwitchTo(Engine.popPrevState());}
|  {Engine.pushPrevState(curLexState);} :SINGLE_LINE_COMMENT //Ending new line characters are parsed separately
|  {Engine.pushPrevState(curLexState);} :MULTI_LINE_COMMENT
}

 SPECIAL_TOKEN [IGNORE_CASE]: {
	
|  | )+ "IF") | "NEXT" | "WEND" | ("END" ( | )+ "SUB") >
}

 SPECIAL_TOKEN: {
	 >
|  > {SwitchTo(Engine.popPrevState());}
//Back through CODE to HTML only; not back through JAVASCRIPT:
| " | "?>" > {
	int prevState;
	do { prevState=Engine.popPrevState(); }
	while(prevState!=CODE);
	SwitchTo( Engine.popPrevState()); //=>DEFAULT/ PRE/ HTML_TAG/ QUOTATION/ APOSTROPHE
	//Plus: unindent in Engine.indent(tok) only if Engine.codeIndent=true.
}
|  >
}

 SPECIAL_TOKEN: {
//Escape to CODE by %> leaves unpaired JSP comment and thus it is not supported.
	 >
|  >
|  >
|  {SwitchTo(Engine.popPrevState());}
}

String File() /*throws...*/: {
	Token t;
} {
	try {
		t=
		{ return Engine.toStringAll(t); }
	}
	catch(TransparentFault ex) { throw ex.source; }
}