1 /* 2 * Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. 3 * Use of this file is governed by the BSD 3-clause license that 4 * can be found in the LICENSE.txt file in the project root. 5 */ 6 7 package org.antlr.v4.codegen; 8 9 import org.antlr.runtime.tree.CommonTreeNodeStream; 10 import org.antlr.v4.analysis.LeftRecursiveRuleAltInfo; 11 import org.antlr.v4.codegen.model.Action; 12 import org.antlr.v4.codegen.model.AltBlock; 13 import org.antlr.v4.codegen.model.BaseListenerFile; 14 import org.antlr.v4.codegen.model.BaseVisitorFile; 15 import org.antlr.v4.codegen.model.Choice; 16 import org.antlr.v4.codegen.model.CodeBlockForAlt; 17 import org.antlr.v4.codegen.model.CodeBlockForOuterMostAlt; 18 import org.antlr.v4.codegen.model.LabeledOp; 19 import org.antlr.v4.codegen.model.LeftRecursiveRuleFunction; 20 import org.antlr.v4.codegen.model.Lexer; 21 import org.antlr.v4.codegen.model.LexerFile; 22 import org.antlr.v4.codegen.model.ListenerFile; 23 import org.antlr.v4.codegen.model.OutputModelObject; 24 import org.antlr.v4.codegen.model.Parser; 25 import org.antlr.v4.codegen.model.ParserFile; 26 import org.antlr.v4.codegen.model.RuleActionFunction; 27 import org.antlr.v4.codegen.model.RuleFunction; 28 import org.antlr.v4.codegen.model.RuleSempredFunction; 29 import org.antlr.v4.codegen.model.SrcOp; 30 import org.antlr.v4.codegen.model.StarBlock; 31 import org.antlr.v4.codegen.model.VisitorFile; 32 import org.antlr.v4.codegen.model.decl.CodeBlock; 33 import org.antlr.v4.misc.Utils; 34 import org.antlr.v4.parse.ANTLRParser; 35 import org.antlr.v4.parse.GrammarASTAdaptor; 36 import org.antlr.v4.tool.Alternative; 37 import org.antlr.v4.tool.ErrorType; 38 import org.antlr.v4.tool.Grammar; 39 import org.antlr.v4.tool.LeftRecursiveRule; 40 import org.antlr.v4.tool.Rule; 41 import org.antlr.v4.tool.ast.ActionAST; 42 import org.antlr.v4.tool.ast.BlockAST; 43 import org.antlr.v4.tool.ast.GrammarAST; 44 import org.antlr.v4.tool.ast.PredAST; 45 import org.stringtemplate.v4.ST; 46 import org.stringtemplate.v4.STGroup; 47 48 import java.util.ArrayList; 49 import java.util.List; 50 import java.util.Stack; 51 52 /** This receives events from SourceGenTriggers.g and asks factory to do work. 53 * Then runs extensions in order on resulting SrcOps to get final list. 54 **/ 55 public class OutputModelController { 56 /** Who does the work? Doesn't have to be CoreOutputModelFactory. */ 57 public OutputModelFactory delegate; 58 59 /** Post-processing CodeGeneratorExtension objects; done in order given. */ 60 public List<CodeGeneratorExtension> extensions = new ArrayList<CodeGeneratorExtension>(); 61 62 /** While walking code in rules, this is set to the tree walker that 63 * triggers actions. 64 */ 65 public SourceGenTriggers walker; 66 67 /** Context set by the SourceGenTriggers.g */ 68 public int codeBlockLevel = -1; 69 public int treeLevel = -1; 70 public OutputModelObject root; // normally ParserFile, LexerFile, ... 71 public Stack<RuleFunction> currentRule = new Stack<RuleFunction>(); 72 public Alternative currentOuterMostAlt; 73 public CodeBlock currentBlock; 74 public CodeBlockForOuterMostAlt currentOuterMostAlternativeBlock; 75 OutputModelController(OutputModelFactory factory)76 public OutputModelController(OutputModelFactory factory) { 77 this.delegate = factory; 78 } 79 addExtension(CodeGeneratorExtension ext)80 public void addExtension(CodeGeneratorExtension ext) { extensions.add(ext); } 81 82 /** Build a file with a parser containing rule functions. Use the 83 * controller as factory in SourceGenTriggers so it triggers codegen 84 * extensions too, not just the factory functions in this factory. 85 */ buildParserOutputModel(boolean header)86 public OutputModelObject buildParserOutputModel(boolean header) { 87 CodeGenerator gen = delegate.getGenerator(); 88 ParserFile file = parserFile(gen.getRecognizerFileName(header)); 89 setRoot(file); 90 file.parser = parser(file); 91 92 Grammar g = delegate.getGrammar(); 93 for (Rule r : g.rules.values()) { 94 buildRuleFunction(file.parser, r); 95 } 96 97 return file; 98 } 99 buildLexerOutputModel(boolean header)100 public OutputModelObject buildLexerOutputModel(boolean header) { 101 CodeGenerator gen = delegate.getGenerator(); 102 LexerFile file = lexerFile(gen.getRecognizerFileName(header)); 103 setRoot(file); 104 file.lexer = lexer(file); 105 106 Grammar g = delegate.getGrammar(); 107 for (Rule r : g.rules.values()) { 108 buildLexerRuleActions(file.lexer, r); 109 } 110 111 return file; 112 } 113 buildListenerOutputModel(boolean header)114 public OutputModelObject buildListenerOutputModel(boolean header) { 115 CodeGenerator gen = delegate.getGenerator(); 116 return new ListenerFile(delegate, gen.getListenerFileName(header)); 117 } 118 buildBaseListenerOutputModel(boolean header)119 public OutputModelObject buildBaseListenerOutputModel(boolean header) { 120 CodeGenerator gen = delegate.getGenerator(); 121 return new BaseListenerFile(delegate, gen.getBaseListenerFileName(header)); 122 } 123 buildVisitorOutputModel(boolean header)124 public OutputModelObject buildVisitorOutputModel(boolean header) { 125 CodeGenerator gen = delegate.getGenerator(); 126 return new VisitorFile(delegate, gen.getVisitorFileName(header)); 127 } 128 buildBaseVisitorOutputModel(boolean header)129 public OutputModelObject buildBaseVisitorOutputModel(boolean header) { 130 CodeGenerator gen = delegate.getGenerator(); 131 return new BaseVisitorFile(delegate, gen.getBaseVisitorFileName(header)); 132 } 133 parserFile(String fileName)134 public ParserFile parserFile(String fileName) { 135 ParserFile f = delegate.parserFile(fileName); 136 for (CodeGeneratorExtension ext : extensions) f = ext.parserFile(f); 137 return f; 138 } 139 parser(ParserFile file)140 public Parser parser(ParserFile file) { 141 Parser p = delegate.parser(file); 142 for (CodeGeneratorExtension ext : extensions) p = ext.parser(p); 143 return p; 144 } 145 lexerFile(String fileName)146 public LexerFile lexerFile(String fileName) { 147 return new LexerFile(delegate, fileName); 148 } 149 lexer(LexerFile file)150 public Lexer lexer(LexerFile file) { 151 return new Lexer(delegate, file); 152 } 153 154 /** Create RuleFunction per rule and update sempreds,actions of parser 155 * output object with stuff found in r. 156 */ buildRuleFunction(Parser parser, Rule r)157 public void buildRuleFunction(Parser parser, Rule r) { 158 RuleFunction function = rule(r); 159 parser.funcs.add(function); 160 pushCurrentRule(function); 161 function.fillNamedActions(delegate, r); 162 163 if ( r instanceof LeftRecursiveRule ) { 164 buildLeftRecursiveRuleFunction((LeftRecursiveRule)r, 165 (LeftRecursiveRuleFunction)function); 166 } 167 else { 168 buildNormalRuleFunction(r, function); 169 } 170 171 Grammar g = getGrammar(); 172 for (ActionAST a : r.actions) { 173 if ( a instanceof PredAST ) { 174 PredAST p = (PredAST)a; 175 RuleSempredFunction rsf = parser.sempredFuncs.get(r); 176 if ( rsf==null ) { 177 rsf = new RuleSempredFunction(delegate, r, function.ctxType); 178 parser.sempredFuncs.put(r, rsf); 179 } 180 rsf.actions.put(g.sempreds.get(p), new Action(delegate, p)); 181 } 182 } 183 184 popCurrentRule(); 185 } 186 buildLeftRecursiveRuleFunction(LeftRecursiveRule r, LeftRecursiveRuleFunction function)187 public void buildLeftRecursiveRuleFunction(LeftRecursiveRule r, LeftRecursiveRuleFunction function) { 188 buildNormalRuleFunction(r, function); 189 190 // now inject code to start alts 191 CodeGenerator gen = delegate.getGenerator(); 192 STGroup codegenTemplates = gen.getTemplates(); 193 194 // pick out alt(s) for primaries 195 CodeBlockForOuterMostAlt outerAlt = (CodeBlockForOuterMostAlt)function.code.get(0); 196 List<CodeBlockForAlt> primaryAltsCode = new ArrayList<CodeBlockForAlt>(); 197 SrcOp primaryStuff = outerAlt.ops.get(0); 198 if ( primaryStuff instanceof Choice ) { 199 Choice primaryAltBlock = (Choice) primaryStuff; 200 primaryAltsCode.addAll(primaryAltBlock.alts); 201 } 202 else { // just a single alt I guess; no block 203 primaryAltsCode.add((CodeBlockForAlt)primaryStuff); 204 } 205 206 // pick out alt(s) for op alts 207 StarBlock opAltStarBlock = (StarBlock)outerAlt.ops.get(1); 208 CodeBlockForAlt altForOpAltBlock = opAltStarBlock.alts.get(0); 209 List<CodeBlockForAlt> opAltsCode = new ArrayList<CodeBlockForAlt>(); 210 SrcOp opStuff = altForOpAltBlock.ops.get(0); 211 if ( opStuff instanceof AltBlock ) { 212 AltBlock opAltBlock = (AltBlock)opStuff; 213 opAltsCode.addAll(opAltBlock.alts); 214 } 215 else { // just a single alt I guess; no block 216 opAltsCode.add((CodeBlockForAlt)opStuff); 217 } 218 219 // Insert code in front of each primary alt to create specialized ctx if there was a label 220 for (int i = 0; i < primaryAltsCode.size(); i++) { 221 LeftRecursiveRuleAltInfo altInfo = r.recPrimaryAlts.get(i); 222 if ( altInfo.altLabel==null ) continue; 223 ST altActionST = codegenTemplates.getInstanceOf("recRuleReplaceContext"); 224 altActionST.add("ctxName", Utils.capitalize(altInfo.altLabel)); 225 Action altAction = 226 new Action(delegate, function.altLabelCtxs.get(altInfo.altLabel), altActionST); 227 CodeBlockForAlt alt = primaryAltsCode.get(i); 228 alt.insertOp(0, altAction); 229 } 230 231 // Insert code to set ctx.stop after primary block and before op * loop 232 ST setStopTokenAST = codegenTemplates.getInstanceOf("recRuleSetStopToken"); 233 Action setStopTokenAction = new Action(delegate, function.ruleCtx, setStopTokenAST); 234 outerAlt.insertOp(1, setStopTokenAction); 235 236 // Insert code to set _prevctx at start of * loop 237 ST setPrevCtx = codegenTemplates.getInstanceOf("recRuleSetPrevCtx"); 238 Action setPrevCtxAction = new Action(delegate, function.ruleCtx, setPrevCtx); 239 opAltStarBlock.addIterationOp(setPrevCtxAction); 240 241 // Insert code in front of each op alt to create specialized ctx if there was an alt label 242 for (int i = 0; i < opAltsCode.size(); i++) { 243 ST altActionST; 244 LeftRecursiveRuleAltInfo altInfo = r.recOpAlts.getElement(i); 245 String templateName; 246 if ( altInfo.altLabel!=null ) { 247 templateName = "recRuleLabeledAltStartAction"; 248 altActionST = codegenTemplates.getInstanceOf(templateName); 249 altActionST.add("currentAltLabel", altInfo.altLabel); 250 } 251 else { 252 templateName = "recRuleAltStartAction"; 253 altActionST = codegenTemplates.getInstanceOf(templateName); 254 altActionST.add("ctxName", Utils.capitalize(r.name)); 255 } 256 altActionST.add("ruleName", r.name); 257 // add label of any lr ref we deleted 258 altActionST.add("label", altInfo.leftRecursiveRuleRefLabel); 259 if (altActionST.impl.formalArguments.containsKey("isListLabel")) { 260 altActionST.add("isListLabel", altInfo.isListLabel); 261 } 262 else if (altInfo.isListLabel) { 263 delegate.getGenerator().tool.errMgr.toolError(ErrorType.CODE_TEMPLATE_ARG_ISSUE, templateName, "isListLabel"); 264 } 265 Action altAction = 266 new Action(delegate, function.altLabelCtxs.get(altInfo.altLabel), altActionST); 267 CodeBlockForAlt alt = opAltsCode.get(i); 268 alt.insertOp(0, altAction); 269 } 270 } 271 buildNormalRuleFunction(Rule r, RuleFunction function)272 public void buildNormalRuleFunction(Rule r, RuleFunction function) { 273 CodeGenerator gen = delegate.getGenerator(); 274 // TRIGGER factory functions for rule alts, elements 275 GrammarASTAdaptor adaptor = new GrammarASTAdaptor(r.ast.token.getInputStream()); 276 GrammarAST blk = (GrammarAST)r.ast.getFirstChildWithType(ANTLRParser.BLOCK); 277 CommonTreeNodeStream nodes = new CommonTreeNodeStream(adaptor,blk); 278 walker = new SourceGenTriggers(nodes, this); 279 try { 280 // walk AST of rule alts/elements 281 function.code = DefaultOutputModelFactory.list(walker.block(null, null)); 282 function.hasLookaheadBlock = walker.hasLookaheadBlock; 283 } 284 catch (org.antlr.runtime.RecognitionException e){ 285 e.printStackTrace(System.err); 286 } 287 288 function.ctxType = gen.getTarget().getRuleFunctionContextStructName(function); 289 290 function.postamble = rulePostamble(function, r); 291 } 292 buildLexerRuleActions(Lexer lexer, final Rule r)293 public void buildLexerRuleActions(Lexer lexer, final Rule r) { 294 if (r.actions.isEmpty()) { 295 return; 296 } 297 298 CodeGenerator gen = delegate.getGenerator(); 299 Grammar g = delegate.getGrammar(); 300 String ctxType = gen.getTarget().getRuleFunctionContextStructName(r); 301 RuleActionFunction raf = lexer.actionFuncs.get(r); 302 if ( raf==null ) { 303 raf = new RuleActionFunction(delegate, r, ctxType); 304 } 305 306 for (ActionAST a : r.actions) { 307 if ( a instanceof PredAST ) { 308 PredAST p = (PredAST)a; 309 RuleSempredFunction rsf = lexer.sempredFuncs.get(r); 310 if ( rsf==null ) { 311 rsf = new RuleSempredFunction(delegate, r, ctxType); 312 lexer.sempredFuncs.put(r, rsf); 313 } 314 rsf.actions.put(g.sempreds.get(p), new Action(delegate, p)); 315 } 316 else if ( a.getType()== ANTLRParser.ACTION ) { 317 raf.actions.put(g.lexerActions.get(a), new Action(delegate, a)); 318 } 319 } 320 321 if (!raf.actions.isEmpty() && !lexer.actionFuncs.containsKey(r)) { 322 // only add to lexer if the function actually contains actions 323 lexer.actionFuncs.put(r, raf); 324 } 325 } 326 rule(Rule r)327 public RuleFunction rule(Rule r) { 328 RuleFunction rf = delegate.rule(r); 329 for (CodeGeneratorExtension ext : extensions) rf = ext.rule(rf); 330 return rf; 331 } 332 rulePostamble(RuleFunction function, Rule r)333 public List<SrcOp> rulePostamble(RuleFunction function, Rule r) { 334 List<SrcOp> ops = delegate.rulePostamble(function, r); 335 for (CodeGeneratorExtension ext : extensions) ops = ext.rulePostamble(ops); 336 return ops; 337 } 338 getGrammar()339 public Grammar getGrammar() { return delegate.getGrammar(); } 340 getGenerator()341 public CodeGenerator getGenerator() { return delegate.getGenerator(); } 342 alternative(Alternative alt, boolean outerMost)343 public CodeBlockForAlt alternative(Alternative alt, boolean outerMost) { 344 CodeBlockForAlt blk = delegate.alternative(alt, outerMost); 345 if ( outerMost ) { 346 currentOuterMostAlternativeBlock = (CodeBlockForOuterMostAlt)blk; 347 } 348 for (CodeGeneratorExtension ext : extensions) blk = ext.alternative(blk, outerMost); 349 return blk; 350 } 351 finishAlternative(CodeBlockForAlt blk, List<SrcOp> ops, boolean outerMost)352 public CodeBlockForAlt finishAlternative(CodeBlockForAlt blk, List<SrcOp> ops, 353 boolean outerMost) 354 { 355 blk = delegate.finishAlternative(blk, ops); 356 for (CodeGeneratorExtension ext : extensions) blk = ext.finishAlternative(blk, outerMost); 357 return blk; 358 } 359 ruleRef(GrammarAST ID, GrammarAST label, GrammarAST args)360 public List<SrcOp> ruleRef(GrammarAST ID, GrammarAST label, GrammarAST args) { 361 List<SrcOp> ops = delegate.ruleRef(ID, label, args); 362 for (CodeGeneratorExtension ext : extensions) { 363 ops = ext.ruleRef(ops); 364 } 365 return ops; 366 } 367 tokenRef(GrammarAST ID, GrammarAST label, GrammarAST args)368 public List<SrcOp> tokenRef(GrammarAST ID, GrammarAST label, GrammarAST args) 369 { 370 List<SrcOp> ops = delegate.tokenRef(ID, label, args); 371 for (CodeGeneratorExtension ext : extensions) { 372 ops = ext.tokenRef(ops); 373 } 374 return ops; 375 } 376 stringRef(GrammarAST ID, GrammarAST label)377 public List<SrcOp> stringRef(GrammarAST ID, GrammarAST label) { 378 List<SrcOp> ops = delegate.stringRef(ID, label); 379 for (CodeGeneratorExtension ext : extensions) { 380 ops = ext.stringRef(ops); 381 } 382 return ops; 383 } 384 385 /** (A|B|C) possibly with ebnfRoot and label */ set(GrammarAST setAST, GrammarAST labelAST, boolean invert)386 public List<SrcOp> set(GrammarAST setAST, GrammarAST labelAST, boolean invert) { 387 List<SrcOp> ops = delegate.set(setAST, labelAST, invert); 388 for (CodeGeneratorExtension ext : extensions) { 389 ops = ext.set(ops); 390 } 391 return ops; 392 } 393 epsilon(Alternative alt, boolean outerMost)394 public CodeBlockForAlt epsilon(Alternative alt, boolean outerMost) { 395 CodeBlockForAlt blk = delegate.epsilon(alt, outerMost); 396 for (CodeGeneratorExtension ext : extensions) blk = ext.epsilon(blk); 397 return blk; 398 } 399 wildcard(GrammarAST ast, GrammarAST labelAST)400 public List<SrcOp> wildcard(GrammarAST ast, GrammarAST labelAST) { 401 List<SrcOp> ops = delegate.wildcard(ast, labelAST); 402 for (CodeGeneratorExtension ext : extensions) { 403 ops = ext.wildcard(ops); 404 } 405 return ops; 406 } 407 action(ActionAST ast)408 public List<SrcOp> action(ActionAST ast) { 409 List<SrcOp> ops = delegate.action(ast); 410 for (CodeGeneratorExtension ext : extensions) ops = ext.action(ops); 411 return ops; 412 } 413 sempred(ActionAST ast)414 public List<SrcOp> sempred(ActionAST ast) { 415 List<SrcOp> ops = delegate.sempred(ast); 416 for (CodeGeneratorExtension ext : extensions) ops = ext.sempred(ops); 417 return ops; 418 } 419 getChoiceBlock(BlockAST blkAST, List<CodeBlockForAlt> alts, GrammarAST label)420 public Choice getChoiceBlock(BlockAST blkAST, List<CodeBlockForAlt> alts, GrammarAST label) { 421 Choice c = delegate.getChoiceBlock(blkAST, alts, label); 422 for (CodeGeneratorExtension ext : extensions) c = ext.getChoiceBlock(c); 423 return c; 424 } 425 getEBNFBlock(GrammarAST ebnfRoot, List<CodeBlockForAlt> alts)426 public Choice getEBNFBlock(GrammarAST ebnfRoot, List<CodeBlockForAlt> alts) { 427 Choice c = delegate.getEBNFBlock(ebnfRoot, alts); 428 for (CodeGeneratorExtension ext : extensions) c = ext.getEBNFBlock(c); 429 return c; 430 } 431 needsImplicitLabel(GrammarAST ID, LabeledOp op)432 public boolean needsImplicitLabel(GrammarAST ID, LabeledOp op) { 433 boolean needs = delegate.needsImplicitLabel(ID, op); 434 for (CodeGeneratorExtension ext : extensions) needs |= ext.needsImplicitLabel(ID, op); 435 return needs; 436 } 437 getRoot()438 public OutputModelObject getRoot() { return root; } 439 setRoot(OutputModelObject root)440 public void setRoot(OutputModelObject root) { this.root = root; } 441 getCurrentRuleFunction()442 public RuleFunction getCurrentRuleFunction() { 443 if ( !currentRule.isEmpty() ) return currentRule.peek(); 444 return null; 445 } 446 pushCurrentRule(RuleFunction r)447 public void pushCurrentRule(RuleFunction r) { currentRule.push(r); } 448 popCurrentRule()449 public RuleFunction popCurrentRule() { 450 if ( !currentRule.isEmpty() ) return currentRule.pop(); 451 return null; 452 } 453 getCurrentOuterMostAlt()454 public Alternative getCurrentOuterMostAlt() { return currentOuterMostAlt; } 455 setCurrentOuterMostAlt(Alternative currentOuterMostAlt)456 public void setCurrentOuterMostAlt(Alternative currentOuterMostAlt) { this.currentOuterMostAlt = currentOuterMostAlt; } 457 setCurrentBlock(CodeBlock blk)458 public void setCurrentBlock(CodeBlock blk) { 459 currentBlock = blk; 460 } 461 getCurrentBlock()462 public CodeBlock getCurrentBlock() { 463 return currentBlock; 464 } 465 setCurrentOuterMostAlternativeBlock(CodeBlockForOuterMostAlt currentOuterMostAlternativeBlock)466 public void setCurrentOuterMostAlternativeBlock(CodeBlockForOuterMostAlt currentOuterMostAlternativeBlock) { 467 this.currentOuterMostAlternativeBlock = currentOuterMostAlternativeBlock; 468 } 469 getCurrentOuterMostAlternativeBlock()470 public CodeBlockForOuterMostAlt getCurrentOuterMostAlternativeBlock() { 471 return currentOuterMostAlternativeBlock; 472 } 473 getCodeBlockLevel()474 public int getCodeBlockLevel() { return codeBlockLevel; } 475 } 476