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 */ 39tree grammar ANTLRTreePrinter; 40 41options 42{ 43 tokenVocab = ANTLR; 44 ASTLabelType = GrammarAST; 45} 46 47@header { 48package org.antlr.grammar.v3; 49import org.antlr.tool.*; 50import java.util.StringTokenizer; 51} 52 53@members { 54protected Grammar grammar; 55protected boolean showActions; 56protected StringBuilder buf = new StringBuilder(300); 57 58private 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 64public 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 75public void out(String s) { 76 buf.append(s); 77} 78 79@Override 80public 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 */ 105public 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 */ 118public 119toString[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 137grammar_ 138 : ^( LEXER_GRAMMAR grammarSpec["lexer " ] ) 139 | ^( PARSER_GRAMMAR grammarSpec["parser "] ) 140 | ^( TREE_GRAMMAR grammarSpec["tree "] ) 141 | ^( COMBINED_GRAMMAR grammarSpec[""] ) 142 ; 143 144attrScope 145 : ^( 'scope' ID ruleAction* ACTION ) 146 ; 147 148grammarSpec[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 159actions 160 : ( action )+ 161 ; 162 163action 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 183optionsSpec 184 : ^( OPTIONS {out(" options {");} 185 (option {out("; ");})+ 186 {out("} ");} 187 ) 188 ; 189 190option 191 : ^( ASSIGN id=ID {out($id.text+"=");} optionValue ) 192 ; 193 194optionValue 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/* 203charSet 204 : #( CHARSET charSetElement ) 205 ; 206 207charSetElement 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 214delegateGrammars 215 : ^( 'import' ( ^(ASSIGN ID ID) | ID )+ ) 216 ; 217 218tokensSpec 219 : ^(TOKENS tokenSpec*) 220 ; 221 222tokenSpec 223 : TOKEN_REF 224 | ^( ASSIGN TOKEN_REF (STRING_LITERAL|CHAR_LITERAL) ) 225 ; 226 227rules 228 : ( rule | precRule )+ 229 ; 230 231rule 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 252precRule 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 273ruleAction 274 : ^(AMPERSAND id=ID a=ACTION ) 275 {if ( showActions ) out("@"+$id.text+"{"+$a.text+"}");} 276 ; 277 278modifier 279@init 280{out($modifier.start.getText()); out(" ");} 281 : 'protected' 282 | 'public' 283 | 'private' 284 | 'fragment' 285 ; 286 287throwsSpec 288 : ^('throws' ID+) 289 ; 290 291ruleScopeSpec 292 : ^( 'scope' ruleAction* (ACTION)? ( ID )* ) 293 ; 294 295block[boolean forceParens] 296@init 297{ 298int 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 321alternative 322 : ^( ALT element* EOA ) 323 ; 324 325exceptionGroup 326 : ( exceptionHandler )+ (finallyClause)? 327 | finallyClause 328 ; 329 330exceptionHandler 331 : ^('catch' ARG_ACTION ACTION) 332 ; 333 334finallyClause 335 : ^('finally' ACTION) 336 ; 337 338rewrite 339 : ^(REWRITES single_rewrite+) 340 | REWRITES 341 | 342 ; 343 344single_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 356rewrite_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 375element 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 418ebnf 419 : block[true] {out(" ");} 420 | ^( OPTIONAL block[true] ) {out("? ");} 421 | ^( CLOSURE block[true] ) {out("* ");} 422 | ^( POSITIVE_CLOSURE block[true] ) {out("+ ");} 423 ; 424 425tree_ 426 : ^(TREE_BEGIN {out(" ^(");} element (element)* {out(") ");} ) 427 ; 428 429atom 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 455ast_suffix 456 : ROOT {out("^");} 457 | BANG {out("!");} 458 ; 459