diff --git a/CHANGES.txt b/CHANGES.txt index 6e802c8b6..ba8d15efb 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -5,6 +5,8 @@ November 18, 2012 * fixed: undefined rule refs caused exception * cleanup, rm dead etypes, add check for ids that cause code gen issues * added notion of one-off error +* added check for v3 backward incompatibilities: +** tree grammars November 17, 2012 diff --git a/tool/src/org/antlr/v4/Tool.java b/tool/src/org/antlr/v4/Tool.java index d7efcaf20..82df03793 100644 --- a/tool/src/org/antlr/v4/Tool.java +++ b/tool/src/org/antlr/v4/Tool.java @@ -46,6 +46,7 @@ import org.antlr.v4.parse.ANTLRParser; import org.antlr.v4.parse.GrammarASTAdaptor; import org.antlr.v4.parse.GrammarTreeVisitor; import org.antlr.v4.parse.ToolANTLRParser; +import org.antlr.v4.parse.v3TreeGrammarException; import org.antlr.v4.runtime.misc.LogManager; import org.antlr.v4.runtime.misc.Nullable; import org.antlr.v4.semantics.SemanticPipeline; @@ -556,7 +557,7 @@ public class Tool { } ANTLRFileStream in = new ANTLRFileStream(file.getAbsolutePath(), grammarEncoding); - GrammarRootAST t = load(in); + GrammarRootAST t = load(fileName, in); return t; } catch (IOException ioe) { @@ -586,17 +587,17 @@ public class Tool { } ANTLRFileStream in = new ANTLRFileStream(importedFile.getAbsolutePath()); - GrammarRootAST root = load(in); + GrammarRootAST root = load(g.fileName, in); Grammar imported = createGrammar(root); imported.fileName = importedFile.getAbsolutePath(); return imported; } public GrammarRootAST loadFromString(String grammar) { - return load(new ANTLRStringStream(grammar)); + return load("", new ANTLRStringStream(grammar)); } - public GrammarRootAST load(CharStream in) { + public GrammarRootAST load(String fileName, CharStream in) { try { GrammarASTAdaptor adaptor = new GrammarASTAdaptor(in); ANTLRLexer lexer = new ANTLRLexer(in); @@ -604,15 +605,20 @@ public class Tool { lexer.tokens = tokens; ToolANTLRParser p = new ToolANTLRParser(tokens, this); p.setTreeAdaptor(adaptor); - ParserRuleReturnScope r = p.grammarSpec(); - GrammarAST root = (GrammarAST)r.getTree(); - if ( root instanceof GrammarRootAST) { - ((GrammarRootAST)root).hasErrors = p.getNumberOfSyntaxErrors()>0; - ((GrammarRootAST)root).tokens = tokens; - if ( grammarOptions!=null ) { - ((GrammarRootAST)root).cmdLineOptions = grammarOptions; + try { + ParserRuleReturnScope r = p.grammarSpec(); + GrammarAST root = (GrammarAST)r.getTree(); + if ( root instanceof GrammarRootAST) { + ((GrammarRootAST)root).hasErrors = p.getNumberOfSyntaxErrors()>0; + ((GrammarRootAST)root).tokens = tokens; + if ( grammarOptions!=null ) { + ((GrammarRootAST)root).cmdLineOptions = grammarOptions; + } + return ((GrammarRootAST)root); } - return ((GrammarRootAST)root); + } + catch (v3TreeGrammarException e) { + errMgr.grammarError(ErrorType.V3_TREE_GRAMMAR, fileName, e.location); } return null; } diff --git a/tool/src/org/antlr/v4/parse/ANTLRLexer.g b/tool/src/org/antlr/v4/parse/ANTLRLexer.g index b289f21e2..be707ec2f 100644 --- a/tool/src/org/antlr/v4/parse/ANTLRLexer.g +++ b/tool/src/org/antlr/v4/parse/ANTLRLexer.g @@ -398,6 +398,7 @@ FRAGMENT : 'fragment' ; LEXER : 'lexer' ; PARSER : 'parser' ; GRAMMAR : 'grammar' ; +TREE_GRAMMAR : 'tree' WSNLCHARS* 'grammar' ; PROTECTED : 'protected' ; PUBLIC : 'public' ; PRIVATE : 'private' ; diff --git a/tool/src/org/antlr/v4/parse/ANTLRParser.g b/tool/src/org/antlr/v4/parse/ANTLRParser.g index cf0b6b099..36eebcb78 100644 --- a/tool/src/org/antlr/v4/parse/ANTLRParser.g +++ b/tool/src/org/antlr/v4/parse/ANTLRParser.g @@ -1,6 +1,6 @@ /* [The "BSD license"] - Copyright (c) 2010 Jim Idle, Terence Parr + Copyright (c) 2012 Jim Idle, Terence Parr All rights reserved. Redistribution and use in source and binary forms, with or without @@ -99,7 +99,7 @@ tokens { @header { /* [The "BSD licence"] - Copyright (c) 2005-2009 Terence Parr + Copyright (c) 2005-20012 Terence Parr All rights reserved. Redistribution and use in source and binary forms, with or without @@ -202,6 +202,7 @@ if ( options!=null ) { grammarType @after { + if ( $tg!=null ) throw new v3TreeGrammarException(tg); if ( $t!=null ) ((GrammarRootAST)$tree).grammarType = $t.type; else ((GrammarRootAST)$tree).grammarType=COMBINED; } @@ -211,6 +212,8 @@ grammarType // A combined lexer and parser specification | g=GRAMMAR -> GRAMMAR[$g, "COMBINED_GRAMMAR"] + | tg=TREE_GRAMMAR + ) ; diff --git a/tool/src/org/antlr/v4/parse/v3TreeGrammarException.java b/tool/src/org/antlr/v4/parse/v3TreeGrammarException.java new file mode 100644 index 000000000..e0f407b41 --- /dev/null +++ b/tool/src/org/antlr/v4/parse/v3TreeGrammarException.java @@ -0,0 +1,12 @@ +package org.antlr.v4.parse; + +import org.antlr.runtime.Token; +import org.antlr.v4.runtime.misc.ParseCancellationException; + +public class v3TreeGrammarException extends ParseCancellationException { + public Token location; + + public v3TreeGrammarException(Token location) { + this.location = location; + } +} diff --git a/tool/src/org/antlr/v4/tool/ErrorType.java b/tool/src/org/antlr/v4/tool/ErrorType.java index 5ba7e4c52..b6c632f47 100644 --- a/tool/src/org/antlr/v4/tool/ErrorType.java +++ b/tool/src/org/antlr/v4/tool/ErrorType.java @@ -116,6 +116,9 @@ public enum ErrorType { LEXER_COMMAND_PLACEMENT_ISSUE(133, "->command in lexer rule must be last element of single outermost alt", ErrorSeverity.ERROR), USE_OF_BAD_WORD(134, "symbol conflicts with generated code in target language or runtime", ErrorSeverity.ERROR), + // Backward incompatibility errors + V3_TREE_GRAMMAR(200, "tree grammars are not supported in ANTLR v4", ErrorSeverity.ERROR_ONE_OFF), + // Dependency sorting errors /** t1.g4 -> t2.g4 -> t3.g4 ->t1.g4 */ diff --git a/tool/src/org/antlr/v4/tool/Grammar.java b/tool/src/org/antlr/v4/tool/Grammar.java index 549e1b056..45e945388 100644 --- a/tool/src/org/antlr/v4/tool/Grammar.java +++ b/tool/src/org/antlr/v4/tool/Grammar.java @@ -238,7 +238,7 @@ public class Grammar implements AttributeResolver { org.antlr.runtime.ANTLRStringStream in = new org.antlr.runtime.ANTLRStringStream(grammarText); in.name = fileName; - this.ast = tool.load(in); + this.ast = tool.load(fileName, in); if ( ast==null ) return; // ensure each node has pointer to surrounding grammar