1/* 2 * [The "BSD license"] 3 * Copyright (c) 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/** Find left-recursive rules */ 34tree grammar LeftRecursiveRuleWalker; 35 36options { 37 tokenVocab=ANTLR; 38 ASTLabelType=GrammarAST; 39} 40 41@header { 42package org.antlr.grammar.v3; 43 44import org.antlr.analysis.*; 45import org.antlr.misc.*; 46import org.antlr.tool.*; 47 48import org.antlr.runtime.BitSet; 49import org.antlr.runtime.DFA; 50} 51 52@members { 53protected Grammar grammar; 54private String ruleName; 55private int outerAlt; // which outer alt of rule? 56public int numAlts; // how many alts for this rule total? 57 58@Override 59public void reportError(RecognitionException ex) 60{ 61 Token token = null; 62 if (ex instanceof MismatchedTokenException) 63 { 64 token = ((MismatchedTokenException)ex).token; 65 } 66 else if (ex instanceof NoViableAltException) 67 { 68 token = ((NoViableAltException)ex).token; 69 } 70 71 ErrorManager.syntaxError( 72 ErrorManager.MSG_SYNTAX_ERROR, 73 grammar, 74 token, 75 "assign.types: " + ex.toString(), 76 ex); 77} 78 79public void setTokenPrec(GrammarAST t, int alt) {} 80public void binaryAlt(GrammarAST altTree, GrammarAST rewriteTree, int alt) {} 81public void ternaryAlt(GrammarAST altTree, GrammarAST rewriteTree, int alt) {} 82public void prefixAlt(GrammarAST altTree, GrammarAST rewriteTree, int alt) {} 83public void suffixAlt(GrammarAST altTree, GrammarAST rewriteTree, int alt) {} 84public void otherAlt(GrammarAST altTree, GrammarAST rewriteTree, int alt) {} 85public void setReturnValues(GrammarAST t) {} 86} 87 88optionsSpec 89 : ^(OPTIONS option+) 90 ; 91 92option 93 : ^(ASSIGN ID optionValue) 94 ; 95 96optionValue 97 : ID 98 | STRING_LITERAL 99 | CHAR_LITERAL 100 | INT 101 ; 102 103charSetElement 104 : CHAR_LITERAL 105 | ^(OR CHAR_LITERAL CHAR_LITERAL) 106 | ^(RANGE CHAR_LITERAL CHAR_LITERAL) 107 ; 108 109public 110rec_rule[Grammar g] returns [boolean isLeftRec] 111@init 112{ 113 grammar = g; 114 outerAlt = 1; 115} 116 : ^( r=RULE id=ID {ruleName=$id.getText();} 117 modifier? 118 ^(ARG ARG_ACTION?) 119 ^(RET ARG_ACTION?) 120 optionsSpec? 121 ruleScopeSpec? 122 (^(AMPERSAND .*))* 123 ruleBlock {$isLeftRec = $ruleBlock.isLeftRec;} 124 exceptionGroup? 125 EOR 126 ) 127 {if ($ruleBlock.isLeftRec) $r.setType(PREC_RULE);} 128 ; 129 130modifier 131 : 'protected' 132 | 'public' 133 | 'private' 134 | 'fragment' 135 ; 136 137ruleScopeSpec 138 : ^('scope' ACTION? ID*) 139 ; 140 141ruleBlock returns [boolean isLeftRec] 142@init{boolean lr=false; this.numAlts = $start.getChildCount();} 143 : ^( BLOCK 144 optionsSpec? 145 ( outerAlternative 146 {if ($outerAlternative.isLeftRec) $isLeftRec = true;} 147 rewrite? 148 {outerAlt++;} 149 )+ 150 EOB 151 ) 152 ; 153 154block 155 : ^( BLOCK 156 optionsSpec? 157 ( ^(ALT element+ EOA) rewrite? )+ 158 EOB 159 ) 160 ; 161 162/** An alt is either prefix, suffix, binary, or ternary operation or "other" */ 163outerAlternative returns [boolean isLeftRec] 164@init 165{ 166GrammarAST rew=(GrammarAST)$start.getNextSibling(); 167if (rew.getType() != REWRITES) 168 rew = null; 169} 170 : (binaryMultipleOp)=> binaryMultipleOp 171 {binaryAlt($start, rew, outerAlt); $isLeftRec=true;} 172 | (binary)=> binary 173 {binaryAlt($start, rew, outerAlt); $isLeftRec=true;} 174 | (ternary)=> ternary 175 {ternaryAlt($start, rew, outerAlt); $isLeftRec=true;} 176 | (prefix)=> prefix 177 {prefixAlt($start, rew, outerAlt);} 178 | (suffix)=> suffix 179 {suffixAlt($start, rew, outerAlt); $isLeftRec=true;} 180 | ^(ALT element+ EOA) // "other" case 181 {otherAlt($start, rew, outerAlt);} 182 ; 183 184binary 185 : ^( ALT (^(BACKTRACK_SEMPRED .*))? recurseNoLabel op=token recurse EOA ) {setTokenPrec($op.t, outerAlt);} 186 ; 187 188binaryMultipleOp 189 : ^( ALT (^(BACKTRACK_SEMPRED .*))? recurseNoLabel ^( BLOCK ( ^( ALT op=token EOA {setTokenPrec($op.t, outerAlt);} ) )+ EOB ) recurse EOA ) 190 ; 191 192ternary 193 : ^( ALT (^(BACKTRACK_SEMPRED .*))? recurseNoLabel op=token recurse token recurse EOA ) {setTokenPrec($op.t, outerAlt);} 194 ; 195 196prefix : ^( ALT (^(BACKTRACK_SEMPRED .*))? {setTokenPrec((GrammarAST)input.LT(1), outerAlt);} ({!((CommonTree)input.LT(1)).getText().equals(ruleName)}? element)+ recurse EOA ) ; 197 198suffix : ^( ALT (^(BACKTRACK_SEMPRED .*))? recurseNoLabel {setTokenPrec((GrammarAST)input.LT(1), outerAlt);} element+ EOA ) ; 199 200recurse 201 : ^(ASSIGN ID recurseNoLabel) 202 | ^(PLUS_ASSIGN ID recurseNoLabel) 203 | recurseNoLabel 204 ; 205 206recurseNoLabel : {((CommonTree)input.LT(1)).getText().equals(ruleName)}? RULE_REF; 207 208/* 209elementNotRecursiveRule 210 : {_t.findFirstType(RULE_REF)!=null && _t.findFirstType(RULE_REF).getText().equals(ruleName)}? 211 e:element 212 ; 213*/ 214 215token returns [GrammarAST t=null] 216 : ^(ASSIGN ID s=token {$t = $s.t;}) 217 | ^(PLUS_ASSIGN ID s=token {$t = $s.t;}) 218 | ^(ROOT s=token {$t = $s.t;}) 219 | ^(BANG s=token {$t = $s.t;}) 220 | a=CHAR_LITERAL {$t = $a;} 221 | b=STRING_LITERAL {$t = $b;} 222 | c=TOKEN_REF {$t = $c;} 223 ; 224 225exceptionGroup 226 : exceptionHandler+ finallyClause? 227 | finallyClause 228 ; 229 230exceptionHandler 231 : ^('catch' ARG_ACTION ACTION) 232 ; 233 234finallyClause 235 : ^('finally' ACTION) 236 ; 237 238rewrite 239 : ^(REWRITES ( ^( REWRITE SEMPRED? (^(ALT .*)|^(TEMPLATE .*)|ACTION|ETC) ) )* ) 240 ; 241 242element 243 : ^(ROOT element) 244 | ^(BANG element) 245 | atom 246 | ^(NOT element) 247 | ^(RANGE atom atom) 248 | ^(ASSIGN ID element) 249 | ^(PLUS_ASSIGN ID element) 250 | ebnf 251 | tree_ 252 | ^(SYNPRED block) 253 | FORCED_ACTION 254 | ACTION 255 | SEMPRED 256 | SYN_SEMPRED 257 | BACKTRACK_SEMPRED 258 | GATED_SEMPRED 259 | EPSILON 260 ; 261 262ebnf: block 263 | ^( OPTIONAL block ) 264 | ^( CLOSURE block ) 265 | ^( POSITIVE_CLOSURE block ) 266 ; 267 268tree_ 269 : ^(TREE_BEGIN element+) 270 ; 271 272atom 273 : ^(RULE_REF ARG_ACTION?) 274 | ^(TOKEN_REF ARG_ACTION?) 275 | CHAR_LITERAL 276 | STRING_LITERAL 277 | WILDCARD 278 | ^(DOT ID atom) // scope override on rule 279 ; 280 281ast_suffix 282 : ROOT 283 | BANG 284 ; 285