Home | History | Annotate | Download | only in v3
      1 /*
      2  [The "BSD license"]
      3  Copyright (c) 2005-2011 Terence Parr
      4  All rights reserved.
      5 
      6  Grammar conversion to ANTLR v3:
      7  Copyright (c) 2011 Sam Harwell
      8  All rights reserved.
      9 
     10  Redistribution and use in source and binary forms, with or without
     11  modification, are permitted provided that the following conditions
     12  are met:
     13  1. Redistributions of source code must retain the above copyright
     14 	notice, this list of conditions and the following disclaimer.
     15  2. Redistributions in binary form must reproduce the above copyright
     16 	notice, this list of conditions and the following disclaimer in the
     17 	documentation and/or other materials provided with the distribution.
     18  3. The name of the author may not be used to endorse or promote products
     19 	derived from this software without specific prior written permission.
     20 
     21  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     22  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     23  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     24  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     25  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     26  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     27  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     30  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31 */
     32 
     33 /** Print out a grammar (no pretty printing).
     34  *
     35  *  Terence Parr
     36  *  University of San Francisco
     37  *  August 19, 2003
     38  */
     39 tree grammar ANTLRTreePrinter;
     40 
     41 options
     42 {
     43 	tokenVocab = ANTLR;
     44 	ASTLabelType = GrammarAST;
     45 }
     46 
     47 @header {
     48 package org.antlr.grammar.v3;
     49 import org.antlr.tool.*;
     50 import java.util.StringTokenizer;
     51 }
     52 
     53 @members {
     54 protected Grammar grammar;
     55 protected boolean showActions;
     56 protected StringBuilder buf = new StringBuilder(300);
     57 
     58 private ANTLRTreePrinter.block_return block(GrammarAST t, boolean forceParens) throws RecognitionException {
     59     ANTLRTreePrinter other = new ANTLRTreePrinter(new CommonTreeNodeStream(t));
     60     other.buf = buf;
     61     return other.block(forceParens);
     62 }
     63 
     64 public final int countAltsForBlock(GrammarAST t) {
     65     int n = 0;
     66     for ( int i = 0; i < t.getChildCount(); i++ )
     67     {
     68         if ( t.getChild(i).getType() == ALT )
     69             n++;
     70     }
     71 
     72     return n;
     73 }
     74 
     75 public void out(String s) {
     76     buf.append(s);
     77 }
     78 
     79 @Override
     80 public void reportError(RecognitionException ex) {
     81     Token token = null;
     82     if (ex instanceof MismatchedTokenException) {
     83         token = ((MismatchedTokenException)ex).token;
     84     } else if (ex instanceof NoViableAltException) {
     85         token = ((NoViableAltException)ex).token;
     86     }
     87 
     88     ErrorManager.syntaxError(
     89         ErrorManager.MSG_SYNTAX_ERROR,
     90         grammar,
     91         token,
     92         "antlr.print: " + ex.toString(),
     93         ex );
     94 }
     95 
     96 /** Normalize a grammar print out by removing all double spaces
     97  *  and trailing/beginning stuff.  FOr example, convert
     98  *
     99  *  ( A  |  B  |  C )*
    100  *
    101  *  to
    102  *
    103  *  ( A | B | C )*
    104  */
    105 public static String normalize(String g) {
    106     StringTokenizer st = new StringTokenizer(g, " ", false);
    107     StringBuffer buf = new StringBuffer();
    108     while ( st.hasMoreTokens() ) {
    109         String w = st.nextToken();
    110         buf.append(w);
    111         buf.append(" ");
    112     }
    113     return buf.toString().trim();
    114 }
    115 }
    116 
    117 /** Call this to figure out how to print */
    118 public
    119 toString[Grammar g, boolean showActions] returns [String s=null]
    120 @init {
    121 	grammar = g;
    122 	this.showActions = showActions;
    123 }
    124 	:	(	grammar_
    125 		|	rule
    126 		|	alternative
    127 		|	element
    128 		|	single_rewrite
    129 		|	rewrite
    130 		|	EOR //{s="EOR";}
    131 		)
    132 		{return normalize(buf.toString());}
    133 	;
    134 
    135 // --------------
    136 
    137 grammar_
    138 	:	^( LEXER_GRAMMAR grammarSpec["lexer " ] )
    139 	|	^( PARSER_GRAMMAR grammarSpec["parser "] )
    140 	|	^( TREE_GRAMMAR grammarSpec["tree "] )
    141 	|	^( COMBINED_GRAMMAR grammarSpec[""] )
    142 	;
    143 
    144 attrScope
    145 	:	^( 'scope' ID ruleAction* ACTION )
    146 	;
    147 
    148 grammarSpec[String gtype]
    149 	:	id=ID {out(gtype+"grammar "+$id.text);}
    150 		(cmt=DOC_COMMENT {out($cmt.text+"\n");} )?
    151 		(optionsSpec)? {out(";\n");}
    152 		(delegateGrammars)?
    153 		(tokensSpec)?
    154 		(attrScope)*
    155 		(actions)?
    156 		rules
    157 	;
    158 
    159 actions
    160 	:	( action )+
    161 	;
    162 
    163 action
    164 @init {
    165 	String scope=null, name=null;
    166 	String action=null;
    167 }
    168 	:	^(	AMPERSAND id1=ID
    169 			(	id2=ID a1=ACTION
    170 				{scope=$id1.text; name=$a1.text; action=$a1.text;}
    171 			|	a2=ACTION
    172 				{scope=null; name=$id1.text; action=$a2.text;}
    173 			)
    174 		)
    175 		{
    176 			if ( showActions )
    177 			{
    178 				out("@"+(scope!=null?scope+"::":"")+name+action);
    179 			}
    180 		}
    181 	;
    182 
    183 optionsSpec
    184 	:	^(	OPTIONS {out(" options {");}
    185 			(option {out("; ");})+
    186 			{out("} ");}
    187 		)
    188 	;
    189 
    190 option
    191 	:	^( ASSIGN id=ID {out($id.text+"=");} optionValue )
    192 	;
    193 
    194 optionValue
    195 	:	id=ID            {out($id.text);}
    196 	|	s=STRING_LITERAL {out($s.text);}
    197 	|	c=CHAR_LITERAL   {out($c.text);}
    198 	|	i=INT            {out($i.text);}
    199 //	|   charSet
    200 	;
    201 
    202 /*
    203 charSet
    204 	:   #( CHARSET charSetElement )
    205 	;
    206 
    207 charSetElement
    208 	:   c:CHAR_LITERAL {out(#c.getText());}
    209 	|   #( OR c1:CHAR_LITERAL c2:CHAR_LITERAL )
    210 	|   #( RANGE c3:CHAR_LITERAL c4:CHAR_LITERAL )
    211 	;
    212 */
    213 
    214 delegateGrammars
    215 	:	^( 'import' ( ^(ASSIGN ID ID) | ID )+ )
    216 	;
    217 
    218 tokensSpec
    219 	:	^(TOKENS tokenSpec*)
    220 	;
    221 
    222 tokenSpec
    223 	:	TOKEN_REF
    224 	|	^( ASSIGN TOKEN_REF (STRING_LITERAL|CHAR_LITERAL) )
    225 	;
    226 
    227 rules
    228 	:	( rule | precRule )+
    229 	;
    230 
    231 rule
    232 	:	^(	RULE id=ID
    233 			(modifier)?
    234 			{out($id.text);}
    235 			^(ARG (arg=ARG_ACTION {out("["+$arg.text+"]");} )? )
    236 			^(RET (ret=ARG_ACTION {out(" returns ["+$ret.text+"]");} )? )
    237 			(throwsSpec)?
    238 			(optionsSpec)?
    239 			(ruleScopeSpec)?
    240 			(ruleAction)*
    241 			{out(" :");}
    242 			{
    243 				if ( input.LA(5) == NOT || input.LA(5) == ASSIGN )
    244 					out(" ");
    245 			}
    246 			b=block[false]
    247 			(exceptionGroup)?
    248 			EOR {out(";\n");}
    249 		)
    250 	;
    251 
    252 precRule
    253 	:	^(	PREC_RULE id=ID
    254 			(modifier)?
    255 			{out($id.text);}
    256 			^(ARG (arg=ARG_ACTION {out("["+$arg.text+"]");} )? )
    257 			^(RET (ret=ARG_ACTION {out(" returns ["+$ret.text+"]");} )? )
    258 			(throwsSpec)?
    259 			(optionsSpec)?
    260 			(ruleScopeSpec)?
    261 			(ruleAction)*
    262 			{out(" :");}
    263 			{
    264 				if ( input.LA(5) == NOT || input.LA(5) == ASSIGN )
    265 					out(" ");
    266 			}
    267 			b=block[false]
    268 			(exceptionGroup)?
    269 			EOR {out(";\n");}
    270 		)
    271 	;
    272 
    273 ruleAction
    274 	:	^(AMPERSAND id=ID a=ACTION )
    275 		{if ( showActions ) out("@"+$id.text+"{"+$a.text+"}");}
    276 	;
    277 
    278 modifier
    279 @init
    280 {out($modifier.start.getText()); out(" ");}
    281 	:	'protected'
    282 	|	'public'
    283 	|	'private'
    284 	|	'fragment'
    285 	;
    286 
    287 throwsSpec
    288 	:	^('throws' ID+)
    289 	;
    290 
    291 ruleScopeSpec
    292 	:	^( 'scope' ruleAction* (ACTION)? ( ID )* )
    293 	;
    294 
    295 block[boolean forceParens]
    296 @init
    297 {
    298 int numAlts = countAltsForBlock($start);
    299 }
    300 	:	^(	BLOCK
    301 			{
    302 				if ( forceParens||numAlts>1 )
    303 				{
    304 					//for ( Antlr.Runtime.Tree.Tree parent = $start.getParent(); parent != null && parent.getType() != RULE; parent = parent.getParent() )
    305 					//{
    306 					//	if ( parent.getType() == BLOCK && countAltsForBlock((GrammarAST)parent) > 1 )
    307 					//	{
    308 					//		out(" ");
    309 					//		break;
    310 					//	}
    311 					//}
    312 					out(" (");
    313 				}
    314 			}
    315 			(optionsSpec {out(" :");} )?
    316 			alternative rewrite ( {out("|");} alternative rewrite )*
    317 			EOB   {if ( forceParens||numAlts>1 ) out(")");}
    318 		 )
    319 	;
    320 
    321 alternative
    322 	:	^( ALT element* EOA )
    323 	;
    324 
    325 exceptionGroup
    326 	:	( exceptionHandler )+ (finallyClause)?
    327 	|	finallyClause
    328 	;
    329 
    330 exceptionHandler
    331 	:	^('catch' ARG_ACTION ACTION)
    332 	;
    333 
    334 finallyClause
    335 	:	^('finally' ACTION)
    336 	;
    337 
    338 rewrite
    339 	:	^(REWRITES single_rewrite+)
    340 	|	REWRITES
    341 	|
    342 	;
    343 
    344 single_rewrite
    345 	:	^(	REWRITE {out(" ->");}
    346 			(	SEMPRED {out(" {"+$SEMPRED.text+"}?");}
    347 			)?
    348 			(	alternative
    349 			|	rewrite_template
    350 			|	ETC {out("...");}
    351 			|	ACTION {out(" {"+$ACTION.text+"}");}
    352 			)
    353 		)
    354 	;
    355 
    356 rewrite_template
    357 	:	^(	TEMPLATE
    358 			(	id=ID {out(" "+$id.text);}
    359 			|	ind=ACTION {out(" ({"+$ind.text+"})");}
    360 			)
    361 			^(	ARGLIST
    362 				{out("(");}
    363 				(	^(	ARG arg=ID {out($arg.text+"=");}
    364 						a=ACTION   {out($a.text);}
    365 					)
    366 				)*
    367 				{out(")");}
    368 			)
    369 			(	DOUBLE_QUOTE_STRING_LITERAL {out(" "+$DOUBLE_QUOTE_STRING_LITERAL.text);}
    370 			|	DOUBLE_ANGLE_STRING_LITERAL {out(" "+$DOUBLE_ANGLE_STRING_LITERAL.text);}
    371 			)?
    372 		)
    373 	;
    374 
    375 element
    376 	:	^(ROOT element) {out("^");}
    377 	|	^(BANG element) {out("!");}
    378 	|	atom
    379 	|	^(NOT {out("~");} element)
    380 	|	^(RANGE atom {out("..");} atom)
    381 	|	^(CHAR_RANGE atom {out("..");} atom)
    382 	|	^(ASSIGN id=ID {out($id.text+"=");} element)
    383 	|	^(PLUS_ASSIGN id2=ID {out($id2.text+"+=");} element)
    384 	|	ebnf
    385 	|	tree_
    386 	|	^( SYNPRED block[true] ) {out("=>");}
    387 	|	a=ACTION  {if ( showActions ) {out("{"); out($a.text); out("}");}}
    388 	|	a2=FORCED_ACTION  {if ( showActions ) {out("{{"); out($a2.text); out("}}");}}
    389 	|	pred=SEMPRED
    390 		{
    391 			if ( showActions )
    392 			{
    393 				out("{");
    394 				out($pred.text);
    395 				out("}?");
    396 			}
    397 			else
    398 			{
    399 				out("{...}?");
    400 			}
    401 		}
    402 	|	spred=SYN_SEMPRED
    403 		{
    404 			String name = $spred.text;
    405 			GrammarAST predAST=grammar.getSyntacticPredicate(name);
    406 			block(predAST, true);
    407 			out("=>");
    408 		}
    409 	|	^(BACKTRACK_SEMPRED .*) // don't print anything (auto backtrack stuff)
    410 	|	gpred=GATED_SEMPRED
    411 		{
    412 		if ( showActions ) {out("{"); out($gpred.text); out("}? =>");}
    413 		else {out("{...}? =>");}
    414 		}
    415 	|	EPSILON
    416 	;
    417 
    418 ebnf
    419 	:	block[true] {out(" ");}
    420 	|	^( OPTIONAL block[true] ) {out("? ");}
    421 	|	^( CLOSURE block[true] )  {out("* ");}
    422 	|	^( POSITIVE_CLOSURE block[true] ) {out("+ ");}
    423 	;
    424 
    425 tree_
    426 	:	^(TREE_BEGIN {out(" ^(");} element (element)* {out(") ");} )
    427 	;
    428 
    429 atom
    430 @init
    431 {out(" ");}
    432 	:	(	^(	RULE_REF		{out($start.toString());}
    433 				(rarg=ARG_ACTION	{out("["+$rarg.toString()+"]");})?
    434 				(ast_suffix)?
    435 			)
    436 		|	^(	TOKEN_REF		{out($start.toString());}
    437 				(targ=ARG_ACTION	{out("["+$targ.toString()+"]");} )?
    438 				(ast_suffix)?
    439 			)
    440 		|	^(	CHAR_LITERAL	{out($start.toString());}
    441 				(ast_suffix)?
    442 			)
    443 		|	^(	STRING_LITERAL	{out($start.toString());}
    444 				(ast_suffix)?
    445 			)
    446 		|	^(	WILDCARD		{out($start.toString());}
    447 				(ast_suffix)?
    448 			)
    449 		)
    450 		{out(" ");}
    451 	|	LABEL {out(" $"+$LABEL.text);} // used in -> rewrites
    452 	|	^(DOT ID {out($ID.text+".");} atom) // scope override on rule
    453 	;
    454 
    455 ast_suffix
    456 	:	ROOT {out("^");}
    457 	|	BANG  {out("!");}
    458 	;
    459