📄 sathercodegenerator.java
字号:
if (((grammar instanceof ParserGrammar) ||
(grammar instanceof LexerGrammar)) &&
grammar.debuggingOutput )
e = "("+e+" and fireSemanticPredicateEvaluated(antlr_oaa.debug.SemanticPredicateEvent.PREDICTING,"+
addSemPred(charFormatter.escapeString(actionStr))+","+actionStr+"))";
else {
e = "("+e+" and ("+actionStr +"))";
}
}
// Generate any syntactic predicates
if ( nIF>0 ) {
if ( alt.synPred != null ) {
println("else");
tabs++;
genSynPred( alt.synPred, e );
closingBracesOfIFSequence++;
}
else {
println("elsif " + e + " then" );
}
}
else {
if ( alt.synPred != null ) {
genSynPred( alt.synPred, e );
}
else {
// when parsing trees, convert null to
// valid tree node with NULL lookahead.
if ( grammar instanceof TreeWalkerGrammar ) {
println("if ( void(sa_t) ) then");
tabs++;
println("sa_t := AST::ASTNULL;");
tabs--;
println("end; -- if");
}
println("if " + e + " then");
}
}
}
nIF++;
tabs++;
genAlt(alt, blk);
tabs--;
if ( !defaultBlock )
println("end; -- if");
}
}
String ps = "";
for (int i=1; i<=closingBracesOfIFSequence; i++) {
ps+="end;";
}
// Restore the AST generation state
genAST = savegenAST;
// restore save text state
saveText=oldsaveTest;
// Return the finishing info.
if ( createdLL1Switch ) {
tabs--;
finishingInfo.postscript = ps; // + "end; -- case";
finishingInfo.generatedSwitch = true;
finishingInfo.generatedAnIf = nIF>0;
//return new JavaBlockFinishingInfo(ps+"}",true,nIF>0); // close up switch statement
}
else {
finishingInfo.postscript = ps;
finishingInfo.generatedSwitch = false;
finishingInfo.generatedAnIf = nIF>0;
// return new JavaBlockFinishingInfo(ps, false,nIF>0);
}
return finishingInfo;
}
private static boolean suitableForCaseExpression(Alternative a) {
return
a.lookaheadDepth == 1 &&
a.semPred == null &&
!a.cache[1].containsEpsilon() &&
a.cache[1].fset.degree()<=caseSizeThreshold;
}
/** Generate code to link an element reference into the AST */
private void genElementAST(AlternativeElement el) {
// handle case where you're not building trees, but are in tree walker.
// Just need to get labels set up.
if ( grammar instanceof TreeWalkerGrammar && !grammar.buildAST ) {
String elementRef;
String astName;
// Generate names and declarations of the AST variable(s)
if (el.getLabel() == null) {
elementRef = lt1Value;
// Generate AST variables for unlabeled stuff
astName = "tmp" + astVarNumber + "_ast";
astVarNumber++;
// Map the generated AST variable in the alternate
mapTreeVariable(el, astName);
// Generate an "input" AST variable also
println( astName + "_in : " + labeledElementASTType + " := " + elementRef + ";");
}
return;
}
if (grammar.buildAST && syntacticPredLevel == 0) {
boolean doNoGuessTest = (
grammar.hasSyntacticPredicate &&
(
el.getLabel() != null ||
el.getAutoGenType() != GrammarElement.AUTO_GEN_BANG
)
);
String elementRef;
String astName;
// Generate names and declarations of the AST variable(s)
if (el.getLabel() != null) {
elementRef = el.getLabel();
astName = el.getLabel() + "_ast";
} else {
elementRef = lt1Value;
// Generate AST variables for unlabeled stuff
astName = "tmp" + astVarNumber + "_ast";
astVarNumber++;
// Generate the declaration (can only build AST's for atoms
GrammarAtom ga = (GrammarAtom)el;
if ( ga.getASTNodeType()!=null ) {
println( astName + " : " + ga.getASTNodeType() + " := void;");
}
else {
println( astName + " : " + labeledElementASTType + ";" );
}
// Map the generated AST variable in the alternate
mapTreeVariable(el, astName);
if (grammar instanceof TreeWalkerGrammar) {
// Generate an "input" AST variable also
println(astName + "_in : " + labeledElementASTType + ";" );
}
}
// Enclose actions with !guessing
if (doNoGuessTest) {
println("if ( input_state.guessing = 0 ) then");
tabs++;
}
// we need to find out the type of argument of
// toke_factory::create. Sather cannot
// overload function unless their signatures
// can clearly be disambiguated. Therefore the
// AST::create( $ANTLR_AST ) : $ANTLR_AST
// and
// AST::create( $ANTLR_TOKEN ) : $ANTLR_AST
// cannot coexist. Therefore we rename them
// create_ast_from_ast and create_ast_from_token, respectively.
String astType = labeledElementASTType;
GrammarAtom atom = (GrammarAtom)el;
if ( atom != null && atom.getASTNodeType() != null ) {
astType = atom.getASTNodeType();
// make this the current AST type, used
// for supsequent AST create's, even though
// the may be temporary AST's
labeledElementASTType = astType;
}
String astCreateString;
if ( grammar instanceof TreeWalkerGrammar )
astCreateString = astType + "::create_from_ast( " + elementRef + " )";
else
astCreateString = astType + "::create_from_token( " + elementRef + " )";
if (el.getLabel() != null) {
println(astName + " := " + astCreateString + ";" );
} else {
elementRef = lt1Value;
println(astName + " := " + astCreateString + ";" );
// Map the generated AST variable in the alternate
if (grammar instanceof TreeWalkerGrammar) {
// set "input" AST variable also
println(astName + "_in := " + elementRef + ";");
}
}
if (genAST) {
switch (el.getAutoGenType()) {
case GrammarElement.AUTO_GEN_NONE:
println("current_ast.add_child( " + astName + " );");
break;
case GrammarElement.AUTO_GEN_CARET:
println("current_ast.make_root( " + astName + " );");
break;
default:
break;
}
}
if (doNoGuessTest) {
tabs--;
println("end; -- if?");
}
}
}
/** Close the try block and generate catch phrases
* if the element has a labeled handler in the rule
*/
private void genErrorCatchForElement(AlternativeElement el) {
if (el.getLabel() == null) return;
String r = el.enclosingRuleName;
if ( grammar instanceof LexerGrammar ) {
r = CodeGenerator.lexerRuleName(el.enclosingRuleName);
}
RuleSymbol rs = (RuleSymbol)grammar.getSymbol(r);
if (rs == null) {
tool.panic("Enclosing rule not found!");
}
ExceptionSpec ex = rs.block.findExceptionSpec(el.getLabel());
if (ex != null) {
tabs--;
println("}*28");
genErrorHandler(ex);
}
}
/** Generate the catch phrases for a user-specified error handler */
private void genErrorHandler(ExceptionSpec ex) {
// Each ExceptionHandler in the ExceptionSpec is a separate catch
for (int i = 0; i < ex.handlers.size(); i++)
{
ExceptionHandler handler = (ExceptionHandler)ex.handlers.elementAt(i);
// Generate catch phrase
println("when " + extractTypeOfAction(handler.exceptionTypeAndName) + " then");
tabs++;
if (grammar.hasSyntacticPredicate) {
println("if ( input_state.guessing = 0 ) then");
tabs++;
}
// When not guessing, execute user handler action
printAction(
processActionForTreeSpecifiers(handler.action.getText(), 0, currentRule, null)
);
if (grammar.hasSyntacticPredicate) {
tabs--;
println("else");
tabs++;
// When guessing, rethrow exception
println("raise exception");
// extractIdOfAction(handler.exceptionTypeAndName) + ";"
tabs--;
println("end; -- if");
}
tabs--;
}
// Close catch phrase
println("end; -- protect");
}
/** Generate a try { opening if the element has a labeled handler in the rule */
private void genErrorTryForElement(AlternativeElement el) {
if (el.getLabel() == null) return;
String r = el.enclosingRuleName;
if ( grammar instanceof LexerGrammar ) {
r = CodeGenerator.lexerRuleName(el.enclosingRuleName);
}
RuleSymbol rs = (RuleSymbol)grammar.getSymbol(r);
if (rs == null) {
tool.panic("Enclosing rule not found!");
}
ExceptionSpec ex = rs.block.findExceptionSpec(el.getLabel());
if (ex != null) {
println("try { // for error handling");
tabs++;
}
}
/** Generate a header that is common to all Sather files */
protected void genHeader() {
println("-- $ANTLR "+Tool.version+": "+
"\""+Tool.fileMinusPath(tool.grammarFile)+"\""+
" -> "+
"\""+grammar.getClassName()+".sa\"$");
}
private void genLiteralsTest() {
println("sa_ttype := test_literals_table(sa_ttype);");
}
private void genLiteralsTestForPartialToken() {
println("sa_ttype := test_literals_table( text.substring( sa_begin, text.length - sa_begin ), sa_ttype );");
}
protected void genMatch(BitSet b) {
}
protected void genMatch(GrammarAtom atom) {
if ( atom instanceof StringLiteralElement ) {
if ( grammar instanceof LexerGrammar ) {
genMatchUsingAtomText(atom);
}
else {
genMatchUsingAtomTokenType(atom);
}
}
else if ( atom instanceof CharLiteralElement ) {
if ( grammar instanceof LexerGrammar ) {
genMatchUsingAtomText(atom);
}
else {
tool.error("cannot ref character literals in grammar: "+atom);
}
}
else if ( atom instanceof TokenRefElement ) {
genMatchUsingAtomText(atom);
}
}
protected void genMatchUsingAtomText(GrammarAtom atom) {
// match() for trees needs the _t cursor
String astArgs="";
if (grammar instanceof TreeWalkerGrammar) {
astArgs="sa_t,";
}
// if in lexer and ! on element, save buffer index to kill later
if ( grammar instanceof LexerGrammar && (!saveText||atom.getAutoGenType()==GrammarElement.AUTO_GEN_BANG) ) {
println("sa_save_index := text.length;");
}
print(atom.not ? "match_not(" : "match(");
_print(astArgs);
// print out what to match
if (atom.atomText.equals("EOF")) {
// horrible hack to handle EOF case
_print("ANTLR_COMMON_TOKEN::EOF_TYPE");
}
else {
_print(atom.atomText);
}
_println(");");
if ( grammar instanceof LexerGrammar && (!saveText||atom.getAutoGenType()==GrammarElement.AUTO_GEN_BANG) ) {
println("text := text.substring( 0 , sa_save_index);"); // kill text atom put in buffer
}
}
protected void genMatchUsingAtomTokenType(GrammarAtom atom) {
// match() for trees needs the _t cursor
String astArgs="";
if (grammar instanceof TreeWalkerGrammar) {
astArgs="sa_t,";
}
// If the literal can be mangled, generate the symbolic constant instead
String mangledName = null;
String s = astArgs + getValueString(atom.getType());
// matching
println( (atom.not ? "match_not(" : "match(") + s + ");");
}
/** Generate the nextToken() rule. nextToken() is a synthetic
* lexer rule that is the implicit OR of all user-defined lexer
* rules.
*/
public void genNextToken() {
// Are there any public rules? If not, then just generate a
// fake nextToken().
boolean hasPublicRules = false;
for (int i = 0; i < grammar.rules.size(); i++) {
RuleSymbol rs = (RuleSymbol)grammar.rules.elementAt(i);
if ( rs.isDefined() && rs.access.equals("public") ) {
hasPublicRules = true;
break;
}
}
if (!hasPublicRules) {
println("");
println("next_token : TOKEN is " );
tabs++;
println("protect");
tabs++;
println("upon_eof;");
tabs--;
println("when $ANTLR_CHAR_STREAM_EXCEPTION then");
tabs++;
println("raise #ANTLR_TOKEN_STREAM_EXCEPTION( exception.str );");
tabs--;
println("end; -- protect");
println("return #ANTLR_COMMON_TOKEN( ANTLR_COMMON_TOKEN::EOF_TYPE, \"\");");
tabs--;
println("end;");
println("");
return;
}
// Create the synthesized nextToken() rule
RuleBlock nextTokenBlk = MakeGrammar.createNextTokenRule(grammar, gra
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -