snapshot
[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 6845]
This commit is contained in:
parent
07625981fb
commit
5baff5d37e
|
@ -0,0 +1,29 @@
|
|||
// args must be <object-model-object>, <fields-resulting-in-STs>
|
||||
parserFile(f, parser) ::= <<
|
||||
// $ANTLR ANTLRVersion> <f.fileName> generatedTimestamp>
|
||||
import org.antlr.runtime.*;
|
||||
|
||||
<parser>
|
||||
>>
|
||||
|
||||
parser(p,funcs,dfaDefs) ::= <<
|
||||
public class <p.name> {
|
||||
<funcs>
|
||||
<dfaDefs>
|
||||
}
|
||||
>>
|
||||
|
||||
DFA(dfa) ::= <<
|
||||
// define <dfa.name>
|
||||
>>
|
||||
|
||||
parserFunction(f,code) ::= <<
|
||||
<f.modifiers:{f | <f> }>void <f.name>(<f.args>) {
|
||||
<code>
|
||||
}
|
||||
>>
|
||||
|
||||
codeFileExtension() ::= ".java"
|
||||
|
||||
true() ::= "true"
|
||||
false() ::= "false"
|
|
@ -76,17 +76,20 @@ FILENAME_EXTENSION_ERROR(arg) ::=
|
|||
|
||||
// code gen errors
|
||||
MISSING_CODE_GEN_TEMPLATES(arg) ::=
|
||||
"cannot find code generation templates <arg>.stg"
|
||||
"cannot find code generation templates for language <arg>"
|
||||
MISSING_CYCLIC_DFA_CODE_GEN_TEMPLATES() ::=
|
||||
"cannot find code generation cyclic DFA templates for language <arg>"
|
||||
CODE_GEN_TEMPLATES_INCOMPLETE(arg) ::=
|
||||
"at least one code generation template missing for language <arg>"
|
||||
"missing code generation template <arg>"
|
||||
CANNOT_CREATE_TARGET_GENERATOR(arg,exception,stackTrace) ::=
|
||||
"cannot create target <arg> code generator: <exception>"
|
||||
CANNOT_COMPUTE_SAMPLE_INPUT_SEQ() ::=
|
||||
"cannot generate a sample input sequence from lookahead DFA"
|
||||
CODE_TEMPLATE_ARG_ISSUE(arg,arg2) ::=
|
||||
"code generation template <arg> has missing, misnamed, or incomplete arg list: <arg2>"
|
||||
NO_MODEL_TO_TEMPLATE_MAPPING(arg) ::=
|
||||
"no mapping to template name for output model class <arg>"
|
||||
|
||||
CANNOT_COMPUTE_SAMPLE_INPUT_SEQ() ::=
|
||||
"cannot generate a sample input sequence from lookahead DFA"
|
||||
|
||||
// grammar interpretation errors
|
||||
/*
|
||||
|
|
|
@ -51,7 +51,14 @@ public abstract class CodeGenerator {
|
|||
}
|
||||
|
||||
public void loadTemplates(String language) {
|
||||
templates = new STGroupFile(TEMPLATE_ROOT+"/"+language+"/"+language+".stg");
|
||||
try {
|
||||
templates = new STGroupFile(TEMPLATE_ROOT+"/"+language+"/"+language+".stg");
|
||||
}
|
||||
catch (IllegalArgumentException iae) {
|
||||
g.tool.errMgr.toolError(ErrorType.CANNOT_CREATE_TARGET_GENERATOR,
|
||||
language);
|
||||
}
|
||||
|
||||
// if ( EMIT_TEMPLATE_DELIMITERS ) {
|
||||
// templates.emitDebugStartStopStrings(true);
|
||||
// templates.doNotEmitDebugStringsForTemplate("codeFileExtension");
|
||||
|
@ -59,6 +66,7 @@ public abstract class CodeGenerator {
|
|||
// }
|
||||
}
|
||||
|
||||
/** The parser, tree parser, etc... variants know to build the model */
|
||||
public abstract OutputModelObject buildOutputModel();
|
||||
|
||||
public void write() {
|
||||
|
@ -70,11 +78,11 @@ public abstract class CodeGenerator {
|
|||
|
||||
// WRITE FILES
|
||||
try {
|
||||
target.genRecognizerFile(g.tool,this,g,outputFileST);
|
||||
target.genRecognizerFile(this,g,outputFileST);
|
||||
if ( templates.isDefined("headerFile") ) {
|
||||
ST extST = templates.getInstanceOf("headerFileExtension");
|
||||
ST headerFileST = null;
|
||||
target.genRecognizerHeaderFile(g.tool,this,g,headerFileST,extST.render());
|
||||
target.genRecognizerHeaderFile(this,g,headerFileST,extST.render());
|
||||
}
|
||||
// // write out the vocab interchange file; used by antlr,
|
||||
// // does not change per target
|
||||
|
|
|
@ -6,11 +6,10 @@ import org.antlr.v4.tool.ErrorType;
|
|||
import org.stringtemplate.v4.ST;
|
||||
import org.stringtemplate.v4.STGroup;
|
||||
import org.stringtemplate.v4.compiler.FormalArgument;
|
||||
import org.stringtemplate.v4.misc.BlankST;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/** Convert output model tree to template hierarchy */
|
||||
public class OutputModelWalker {
|
||||
|
@ -30,29 +29,52 @@ public class OutputModelWalker {
|
|||
public ST walk(OutputModelObject omo) {
|
||||
// CREATE TEMPLATE FOR THIS OUTPUT OBJECT
|
||||
String templateName = modelToTemplateMap.get(omo.getClass());
|
||||
if ( templateName == null ) {
|
||||
tool.errMgr.toolError(ErrorType.NO_MODEL_TO_TEMPLATE_MAPPING, omo.getClass().getSimpleName());
|
||||
return new BlankST();
|
||||
}
|
||||
ST st = templates.getInstanceOf(templateName);
|
||||
if ( st.impl.formalArguments== FormalArgument.UNKNOWN ) {
|
||||
if ( st == null ) {
|
||||
tool.errMgr.toolError(ErrorType.CODE_GEN_TEMPLATES_INCOMPLETE, templateName);
|
||||
return new BlankST();
|
||||
}
|
||||
if ( st.impl.formalArguments == FormalArgument.UNKNOWN ) {
|
||||
tool.errMgr.toolError(ErrorType.CODE_TEMPLATE_ARG_ISSUE, templateName, "<none>");
|
||||
return st;
|
||||
}
|
||||
// todo: chk arg-field mismtch
|
||||
Set<String> argNames = st.impl.formalArguments.keySet();
|
||||
String arg = argNames.iterator().next(); // should be just one
|
||||
|
||||
// PASS IN OUTPUT OBJECT TO TEMPLATE
|
||||
st.add(arg, omo); // set template attribute of correct name
|
||||
List<String> kids = omo.getChildren();
|
||||
|
||||
for (String fieldName : omo.getChildren()) {
|
||||
if ( argNames.contains(fieldName) ) continue; // they won't use so don't compute
|
||||
LinkedHashMap<String,FormalArgument> formalArgs = st.impl.formalArguments;
|
||||
Set<String> argNames = formalArgs.keySet();
|
||||
Iterator<String> it = argNames.iterator();
|
||||
|
||||
// PASS IN OUTPUT MODEL OBJECT TO TEMPLATE
|
||||
String modelArgName = it.next(); // ordered so this is first arg
|
||||
st.add(modelArgName, omo);
|
||||
|
||||
// ENSURE TEMPLATE ARGS AND CHILD FIELDS MATCH UP
|
||||
while ( it.hasNext() ) {
|
||||
String argName = it.next();
|
||||
if ( !kids.contains(argName) ) {
|
||||
tool.errMgr.toolError(ErrorType.CODE_TEMPLATE_ARG_ISSUE, templateName, argName);
|
||||
return st;
|
||||
}
|
||||
}
|
||||
|
||||
// COMPUTE STs FOR EACH NESTED MODEL OBJECT NAMED AS ARG BY TEMPLATE
|
||||
if ( kids!=null ) for (String fieldName : kids) {
|
||||
if ( !argNames.contains(fieldName) ) continue; // they won't use so don't compute
|
||||
//System.out.println("computing ST for field "+fieldName+" of "+omo.getClass());
|
||||
try {
|
||||
Field fi = omo.getClass().getField(fieldName);
|
||||
Object o = fi.get(omo);
|
||||
if ( o instanceof OutputModelObject ) {
|
||||
if ( o instanceof OutputModelObject ) { // SINGLE MODEL OBJECT?
|
||||
OutputModelObject nestedOmo = (OutputModelObject)o;
|
||||
ST nestedST = walk(nestedOmo);
|
||||
st.add(fieldName, nestedST);
|
||||
}
|
||||
else if ( o instanceof Collection) {
|
||||
else if ( o instanceof Collection ) { // LIST OF MODEL OBJECTS?
|
||||
Collection<? extends OutputModelObject> nestedOmos = (Collection)o;
|
||||
for (OutputModelObject nestedOmo : nestedOmos) {
|
||||
ST nestedST = walk(nestedOmo);
|
||||
|
@ -64,7 +86,7 @@ public class OutputModelWalker {
|
|||
}
|
||||
}
|
||||
catch (NoSuchFieldException nsfe) {
|
||||
tool.errMgr.toolError(ErrorType.CODE_TEMPLATE_ARG_ISSUE, templateName, fieldName);
|
||||
tool.errMgr.toolError(ErrorType.CODE_TEMPLATE_ARG_ISSUE, templateName, nsfe.getMessage());
|
||||
}
|
||||
catch (IllegalAccessException iae) {
|
||||
tool.errMgr.toolError(ErrorType.CODE_TEMPLATE_ARG_ISSUE, templateName, fieldName);
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
package org.antlr.v4.codegen;
|
||||
|
||||
import org.antlr.v4.codegen.src.OutputModelObject;
|
||||
import org.antlr.v4.codegen.src.Parser;
|
||||
import org.antlr.v4.codegen.src.ParserFile;
|
||||
import org.antlr.v4.codegen.src.RuleFunction;
|
||||
import org.antlr.v4.codegen.src.*;
|
||||
import org.antlr.v4.tool.Grammar;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
@ -16,6 +13,7 @@ public class ParserGenerator extends CodeGenerator {
|
|||
put(ParserFile.class, "parserFile");
|
||||
put(Parser.class, "parser");
|
||||
put(RuleFunction.class, "parserFunction");
|
||||
put(DFADef.class, "DFA");
|
||||
}};
|
||||
|
||||
public ParserGenerator(Grammar g) {
|
||||
|
@ -24,8 +22,6 @@ public class ParserGenerator extends CodeGenerator {
|
|||
|
||||
public OutputModelObject buildOutputModel() {
|
||||
Parser p = new Parser(g);
|
||||
ParserFile f = new ParserFile(p, getRecognizerFileName());
|
||||
|
||||
return f;
|
||||
return new ParserFile(p, getRecognizerFileName());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
tree grammar SourceGenTriggers;
|
||||
options {
|
||||
language = Java;
|
||||
tokenVocab = ANTLRParser;
|
||||
ASTLabelType = GrammarAST;
|
||||
// superClass = NFABytecodeGenerator;
|
||||
}
|
||||
|
||||
@header {
|
||||
package org.antlr.v4.codegen;
|
||||
import org.antlr.v4.codegen.nfa.*;
|
||||
import org.antlr.v4.tool.GrammarAST;
|
||||
import org.antlr.v4.tool.GrammarASTWithOptions;
|
||||
import org.antlr.v4.tool.LexerGrammar;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
}
|
||||
|
||||
block
|
||||
: ^( BLOCK (^(OPTIONS .+))?
|
||||
( alternative
|
||||
)+
|
||||
)
|
||||
;
|
||||
|
||||
alternative
|
||||
: ^(ALT_REWRITE a=alternative .)
|
||||
| ^(ALT EPSILON)
|
||||
| ^(ALT (e=element )+)
|
||||
;
|
||||
|
||||
element
|
||||
: labeledElement
|
||||
| atom
|
||||
| ebnf
|
||||
| ACTION
|
||||
| SEMPRED
|
||||
| GATED_SEMPRED
|
||||
| treeSpec
|
||||
;
|
||||
|
||||
labeledElement
|
||||
: ^(ASSIGN ID atom )
|
||||
| ^(ASSIGN ID block)
|
||||
| ^(PLUS_ASSIGN ID atom)
|
||||
| ^(PLUS_ASSIGN ID block)
|
||||
;
|
||||
|
||||
treeSpec
|
||||
: ^(TREE_BEGIN (e=element )+)
|
||||
;
|
||||
|
||||
ebnf
|
||||
@init {
|
||||
GrammarASTWithOptions blk = (GrammarASTWithOptions)$start.getChild(0);
|
||||
String greedyOption = blk.getOption("greedy");
|
||||
}
|
||||
: ^(astBlockSuffix block)
|
||||
| ^(OPTIONAL block)
|
||||
|
||||
| ^(CLOSURE block)
|
||||
|
||||
| ^(POSITIVE_CLOSURE block)
|
||||
|
||||
| block
|
||||
;
|
||||
|
||||
astBlockSuffix
|
||||
: ROOT
|
||||
| IMPLIES
|
||||
| BANG
|
||||
;
|
||||
|
||||
atom
|
||||
: ^(ROOT range)
|
||||
| ^(BANG range)
|
||||
| ^(ROOT notSet)
|
||||
| ^(BANG notSet)
|
||||
| notSet
|
||||
| range
|
||||
| ^(DOT ID terminal)
|
||||
| ^(DOT ID ruleref)
|
||||
| ^(WILDCARD .)
|
||||
| WILDCARD
|
||||
| terminal
|
||||
| ruleref
|
||||
;
|
||||
|
||||
notSet
|
||||
: ^(NOT terminal)
|
||||
| ^(NOT block)
|
||||
;
|
||||
|
||||
ruleref
|
||||
: ^(ROOT ^(RULE_REF ARG_ACTION?))
|
||||
| ^(BANG ^(RULE_REF ARG_ACTION?))
|
||||
| ^(RULE_REF ARG_ACTION?)
|
||||
;
|
||||
|
||||
range
|
||||
: ^(RANGE a=STRING_LITERAL b=STRING_LITERAL)
|
||||
|
||||
;
|
||||
|
||||
terminal
|
||||
: ^(STRING_LITERAL .)
|
||||
| STRING_LITERAL
|
||||
| ^(TOKEN_REF ARG_ACTION .)
|
||||
| ^(TOKEN_REF .)
|
||||
| TOKEN_REF
|
||||
| ^(ROOT terminal)
|
||||
| ^(BANG terminal)
|
||||
;
|
|
@ -1,6 +1,5 @@
|
|||
package org.antlr.v4.codegen;
|
||||
|
||||
import org.antlr.v4.Tool;
|
||||
import org.antlr.v4.automata.Label;
|
||||
import org.antlr.v4.tool.Grammar;
|
||||
import org.stringtemplate.v4.ST;
|
||||
|
@ -36,9 +35,8 @@ public class Target {
|
|||
ANTLRLiteralCharValueEscape['\''] = "\\'";
|
||||
}
|
||||
|
||||
protected void genRecognizerFile(Tool tool,
|
||||
CodeGenerator generator,
|
||||
Grammar grammar,
|
||||
protected void genRecognizerFile(CodeGenerator generator,
|
||||
Grammar g,
|
||||
ST outputFileST)
|
||||
throws IOException
|
||||
{
|
||||
|
@ -46,9 +44,8 @@ public class Target {
|
|||
generator.write(outputFileST, fileName);
|
||||
}
|
||||
|
||||
protected void genRecognizerHeaderFile(Tool tool,
|
||||
CodeGenerator generator,
|
||||
Grammar grammar,
|
||||
protected void genRecognizerHeaderFile(CodeGenerator generator,
|
||||
Grammar g,
|
||||
ST headerFileST,
|
||||
String extName) // e.g., ".h"
|
||||
throws IOException
|
||||
|
|
|
@ -6,5 +6,9 @@ import org.antlr.v4.automata.DFA;
|
|||
public class DFADef extends OutputModelObject {
|
||||
public String name;
|
||||
public DFA dfa;
|
||||
|
||||
|
||||
public DFADef(String name, DFA dfa) {
|
||||
this.dfa = dfa;
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import java.util.List;
|
|||
|
||||
/** */
|
||||
public abstract class OutputModelObject {
|
||||
//public abstract ST getSt();
|
||||
//public ST st;
|
||||
|
||||
/** If the output model object encloses some other model objects,
|
||||
* we need to be able to walk them. Rather than make each class
|
||||
|
@ -13,6 +13,7 @@ public abstract class OutputModelObject {
|
|||
* as a homogeneous tree structure. Returns a list of field names
|
||||
* of type OutputModelObject that should be walked to complete model.
|
||||
*/
|
||||
// TODO: make list of Fields to avoid repeated look up
|
||||
public List<String> getChildren() {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.antlr.v4.codegen.src;
|
||||
|
||||
import org.antlr.v4.automata.DFA;
|
||||
import org.antlr.v4.misc.IntSet;
|
||||
import org.antlr.v4.tool.Grammar;
|
||||
import org.antlr.v4.tool.Rule;
|
||||
|
@ -11,12 +12,17 @@ import java.util.List;
|
|||
public class Parser extends OutputModelObject {
|
||||
public String name;
|
||||
public List<RuleFunction> funcs = new ArrayList<RuleFunction>();
|
||||
public List<DFADef> dfaDefs;
|
||||
public List<DFADef> dfaDefs = new ArrayList<DFADef>();
|
||||
public List<IntSet> bitsetDefs;
|
||||
|
||||
public Parser(Grammar g) {
|
||||
name = g.getRecognizerName();
|
||||
for (Rule r : g.rules.values()) funcs.add( new RuleFunction(r) );
|
||||
|
||||
// build DFA, bitset defs
|
||||
for (DFA dfa : g.decisionDFAs.values()) {
|
||||
dfaDefs.add( new DFADef("DFA"+dfa.decision, dfa) );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
package org.antlr.v4.codegen.src;
|
||||
|
||||
import org.antlr.runtime.tree.CommonTreeNodeStream;
|
||||
import org.antlr.v4.codegen.SourceGenTriggers;
|
||||
import org.antlr.v4.misc.Utils;
|
||||
import org.antlr.v4.parse.ANTLRParser;
|
||||
import org.antlr.v4.parse.GrammarASTAdaptor;
|
||||
import org.antlr.v4.tool.Attribute;
|
||||
import org.antlr.v4.tool.GrammarAST;
|
||||
import org.antlr.v4.tool.Rule;
|
||||
|
@ -40,6 +44,17 @@ public class RuleFunction extends OutputModelObject {
|
|||
tokenLabels = r.getTokenRefs();
|
||||
exceptions = Utils.nodesToStrings(r.exceptionActions);
|
||||
if ( r.finallyAction!=null ) finallyAction = r.finallyAction.getText();
|
||||
|
||||
GrammarASTAdaptor adaptor = new GrammarASTAdaptor(r.ast.token.getInputStream());
|
||||
GrammarAST blk = (GrammarAST)r.ast.getFirstChildWithType(ANTLRParser.BLOCK);
|
||||
CommonTreeNodeStream nodes = new CommonTreeNodeStream(adaptor,blk);
|
||||
SourceGenTriggers gen = new SourceGenTriggers(nodes);
|
||||
try {
|
||||
gen.block(); // GEN Instr OBJECTS
|
||||
}
|
||||
catch (Exception e){
|
||||
e.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -62,6 +62,8 @@ public enum ErrorType {
|
|||
MISSING_CODE_GEN_TEMPLATES(ErrorSeverity.ERROR, false, true),
|
||||
CANNOT_CREATE_TARGET_GENERATOR(ErrorSeverity.ERROR, false, true),
|
||||
CODE_TEMPLATE_ARG_ISSUE(ErrorSeverity.ERROR, false, true),
|
||||
CODE_GEN_TEMPLATES_INCOMPLETE(ErrorSeverity.ERROR, false, true),
|
||||
NO_MODEL_TO_TEMPLATE_MAPPING(ErrorSeverity.ERROR, false, true),
|
||||
|
||||
// Grammar errors
|
||||
SYNTAX_ERROR(ErrorSeverity.ERROR, true, true),
|
||||
|
|
Loading…
Reference in New Issue