📄 antlr.g
字号:
header {
package antlr;
}
{
import java.util.Enumeration;
import java.io.DataInputStream;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.IOException;
}
/* ANTLR Translator Generator
* Project led by Terence Parr at http://www.jGuru.com
* Software rights: http://www.antlr.org/RIGHTS.html
*
* $Id: antlr.g,v 1.1 2002/11/08 17:37:29 agno Exp $
*/
class ANTLRParser extends Parser;
options {
exportVocab=ANTLR;
defaultErrorHandler=false;
k=2;
}
tokens {
"tokens";
}
{
private static final boolean DEBUG_PARSER = false;
ANTLRGrammarParseBehavior behavior;
Tool tool;
protected int blockNesting= -1;
public ANTLRParser(
TokenBuffer tokenBuf,
ANTLRGrammarParseBehavior behavior_,
Tool tool_
) {
super(tokenBuf, 1);
tokenNames = _tokenNames;
behavior = behavior_;
tool = tool_;
}
private boolean lastInRule() throws TokenStreamException {
if ( blockNesting==0 && (LA(1)==SEMI || LA(1)==LITERAL_exception || LA(1)==OR) ) {
return true;
}
return false;
}
private void checkForMissingEndRule(Token label) {
if ( label.getColumn()==1 ) {
Tool.warning("did you forget to terminate previous rule?", getFilename(), label.getLine());
}
}
}
grammar
:
( "header" (n:STRING_LITERAL)? h:ACTION {behavior.refHeaderAction(n,h);} )*
( fileOptionsSpec )?
( classDef )*
EOF
;
exception catch [RecognitionException ex] {
reportError("rule grammar trapped: "+ex.toString());
consumeUntil(EOF);
}
classDef
{String doc=null;}
:
( a:ACTION { behavior.refPreambleAction(a);} )?
( d:DOC_COMMENT {doc=d.getText();} )?
( ("lexclass" | "class" id "extends" "Lexer" ) => lexerSpec[doc]
| ( "class" id "extends" "TreeParser" ) => treeParserSpec[doc]
| parserSpec[doc]
)
rules
{ behavior.endGrammar(); }
;
exception catch [RecognitionException ex] {
if ( ex instanceof NoViableAltException ) {
NoViableAltException e = (NoViableAltException)ex;
if ( e.token.getType()==DOC_COMMENT ) {
reportError("line "+ex.line+": JAVADOC comments may only prefix rules and grammars");
}
else {
reportError("rule classDef trapped: "+ex.toString());
}
}
else {
reportError("rule classDef trapped: "+ex.toString());
}
behavior.abortGrammar();
boolean consuming = true;
// consume everything until the next class definition or EOF
while (consuming) {
consume();
switch(LA(1)) {
case LITERAL_class:
case LITERAL_lexclass:
case EOF:
consuming = false;
break;
}
}
}
fileOptionsSpec
{ Token idTok; Token value; }
: OPTIONS
(
idTok = id
ASSIGN
value = optionValue
{ behavior.setFileOption(idTok, value,getInputState().filename); }
SEMI
)*
RCURLY
;
parserOptionsSpec
{ Token idTok; Token value; }
: OPTIONS
(
idTok = id
ASSIGN
value = optionValue
{ behavior.setGrammarOption(idTok, value); }
SEMI
)*
RCURLY
;
treeParserOptionsSpec
{ Token idTok; Token value; }
: OPTIONS
(
idTok = id
ASSIGN
value = optionValue
{ behavior.setGrammarOption(idTok, value); }
SEMI
)*
RCURLY
;
lexerOptionsSpec
{ Token idTok; Token value; BitSet b; }
:
OPTIONS
( // Special case for vocabulary option because it has a bit-set
"charVocabulary"
ASSIGN
b = charSet
SEMI
{ behavior.setCharVocabulary(b); }
| idTok = id
ASSIGN
value = optionValue
{ behavior.setGrammarOption(idTok, value); }
SEMI
)*
RCURLY
;
subruleOptionsSpec
{ Token idTok; Token value; }
: OPTIONS
( idTok = id
ASSIGN
value = optionValue
{ behavior.setSubruleOption(idTok, value); }
SEMI
)*
RCURLY
;
// optionValue returns a Token which may be one of several things:
// STRING_LITERAL -- a quoted string
// CHAR_LITERAL -- a single quoted character
// INT -- an integer
// RULE_REF or TOKEN_REF -- an identifier
optionValue
returns [ Token retval ]
{ retval = null; }
: retval = qualifiedID
| sl:STRING_LITERAL { retval = sl; }
| cl:CHAR_LITERAL { retval = cl; }
| il:INT { retval = il; }
;
charSet
returns [ BitSet b ]
{
b = null;
BitSet tmpSet = null;
}
:
// TODO: generate a bit set
b = setBlockElement
(
OR
tmpSet = setBlockElement
{ b.orInPlace(tmpSet); }
)*
;
setBlockElement
returns [ BitSet b ]
{
b = null;
int rangeMin = 0;
}
:
c1:CHAR_LITERAL
{
rangeMin = ANTLRLexer.tokenTypeForCharLiteral(c1.getText());
b = BitSet.of(rangeMin);
}
(
RANGE c2:CHAR_LITERAL
{
int rangeMax = ANTLRLexer.tokenTypeForCharLiteral(c2.getText());
if (rangeMax < rangeMin) {
tool.error("Malformed range line "+c1.getLine());
}
for (int i = rangeMin+1; i <= rangeMax; i++) {
b.add(i);
}
}
)?
;
tokensSpec
: TOKENS
( ( {s1=null;}
t1:TOKEN_REF
( ASSIGN s1:STRING_LITERAL )?
{behavior.defineToken(t1, s1);}
(tokensSpecOptions[t1])?
| s3:STRING_LITERAL
{behavior.defineToken(null, s3);}
(tokensSpecOptions[s3])?
)
SEMI
)+
RCURLY
;
tokensSpecOptions[Token t]
{
Token o=null, v=null;
}
: OPEN_ELEMENT_OPTION
o=id ASSIGN v=optionValue
{behavior.refTokensSpecElementOption(t,o,v);}
(
SEMI
o=id ASSIGN v=optionValue
{behavior.refTokensSpecElementOption(t,o,v);}
)*
CLOSE_ELEMENT_OPTION
;
superClass returns [String sup]
{sup=null;}
: LPAREN
{sup = LT(1).getText();}
(TOKEN_REF|RULE_REF)
RPAREN
;
parserSpec[String doc]
{
Token idTok;
String sup=null;
}
: "class"
idTok = id
( "extends" "Parser"
(sup=superClass)?
| {
System.out.println("warning: line " +
idTok.getLine() + ": use 'class X extends Parser'");
}
)
{behavior.startParser(getFilename(), idTok, sup, doc);}
SEMI
(parserOptionsSpec)?
{ behavior.endOptions(); }
(tokensSpec)?
( a:ACTION {behavior.refMemberAction(a);} )?
;
lexerSpec[String doc]
{
Token idTok;
String sup=null;
}
: ( lc:"lexclass"
idTok = id
{ System.out.println("warning: line " + lc.getLine() + ": 'lexclass' is deprecated; use 'class X extends Lexer'"); }
| "class"
idTok = id
"extends"
"Lexer"
(sup=superClass)?
)
{behavior.startLexer(getFilename(), idTok,sup,doc);}
SEMI
(lexerOptionsSpec)?
{ behavior.endOptions(); }
(tokensSpec)?
( a:ACTION {behavior.refMemberAction(a);} )?
;
treeParserSpec[String doc]
{
Token idTok;
String sup=null;
}
: "class"
idTok = id
"extends"
"TreeParser"
(sup=superClass)?
{behavior.startTreeWalker(getFilename(), idTok,sup,doc);}
SEMI
(treeParserOptionsSpec)?
{ behavior.endOptions(); }
(tokensSpec)?
( a:ACTION {behavior.refMemberAction(a);} )?
;
rules
: (
options {
// limitation of appox LL(k) says ambig upon
// DOC_COMMENT TOKEN_REF, but that's an impossible sequence
warnWhenFollowAmbig=false;
}
: rule
)+
;
rule
{
String access="public";
Token idTok;
String doc=null;
boolean ruleAutoGen = true;
blockNesting = -1; // block increments, so -1 to make rule at level 0
}
:
( d:DOC_COMMENT {doc=d.getText();}
)?
( p1:"protected" {access=p1.getText();}
| p2:"public" {access=p2.getText();}
| p3:"private" {access=p3.getText();}
)?
idTok = id
( BANG { ruleAutoGen = false; } )?
{
behavior.defineRuleName(idTok, access, ruleAutoGen, doc);
}
( aa:ARG_ACTION { behavior.refArgAction(aa); } )?
( "returns" rt:ARG_ACTION { behavior.refReturnAction(rt); } )?
( throwsSpec )?
( ruleOptionsSpec )?
(a:ACTION {behavior.refInitAction(a);})?
COLON block SEMI
( exceptionGroup )?
{behavior.endRule(idTok.getText());}
;
/*
//
// for now, syntax error in rule aborts the whole grammar
//
exception catch [ParserException ex] {
behavior.abortRule(idTok);
behavior.hasError();
// Consume until something that looks like end of a rule
consume();
while (LA(1) != SEMI && LA(1) != EOF) {
consume();
}
consume();
}
*/
ruleOptionsSpec
{ Token idTok; Token value; }
: OPTIONS
(
idTok = id
ASSIGN
value = optionValue
{ behavior.setRuleOption(idTok, value); }
SEMI
)*
RCURLY
;
throwsSpec
{
String t=null;
Token a,b;
}
: "throws" a=id {t=a.getText();}
( COMMA b=id {t+=","+b.getText();} )*
{ behavior.setUserExceptions(t); }
;
block
: {blockNesting++;}
alternative ( OR alternative )*
{blockNesting--;}
;
alternative
{ boolean altAutoGen = true; }
:
(BANG { altAutoGen=false;} )?
{behavior.beginAlt(altAutoGen);}
( element )* ( exceptionSpecNoLabel )?
{behavior.endAlt();}
;
exceptionGroup
: { behavior.beginExceptionGroup(); }
( exceptionSpec )+
{ behavior.endExceptionGroup(); }
;
exceptionSpec
{ Token labelAction = null; }
:
"exception"
( aa:ARG_ACTION { labelAction = aa; } )?
{ behavior.beginExceptionSpec(labelAction); }
( exceptionHandler )*
{ behavior.endExceptionSpec(); }
;
exceptionSpecNoLabel
:
"exception"
{ behavior.beginExceptionSpec(null); }
( exceptionHandler )*
{ behavior.endExceptionSpec(); }
;
exceptionHandler
{ Token exType; Token exName; }
:
"catch"
a1:ARG_ACTION
a2:ACTION
{ behavior.refExceptionHandler(a1, a2); }
;
element
: elementNoOptionSpec (elementOptionSpec)?
;
elementOptionSpec
{
Token o=null, v=null;
}
: OPEN_ELEMENT_OPTION
o=id ASSIGN v=optionValue
{behavior.refElementOption(o,v);}
(
SEMI
o=id ASSIGN v=optionValue
{behavior.refElementOption(o,v);}
)*
CLOSE_ELEMENT_OPTION
;
elementNoOptionSpec
{
Token label = null;
Token assignId = null;
Token args = null;
int autoGen = GrammarElement.AUTO_GEN_NONE;
}
: assignId=id
ASSIGN
( label=id COLON {checkForMissingEndRule(label);} )?
( rr:RULE_REF
( aa:ARG_ACTION { args=aa; } )?
( BANG { autoGen = GrammarElement.AUTO_GEN_BANG; } )?
{ behavior.refRule(assignId, rr, label, args, autoGen); }
| // this syntax only valid for lexer
tr:TOKEN_REF
( aa2:ARG_ACTION { args=aa2; } )?
{ behavior.refToken(assignId, tr, label, args, false, autoGen, lastInRule()); }
)
|
(label=id COLON {checkForMissingEndRule(label);} )?
( r2:RULE_REF
( aa3:ARG_ACTION { args=aa3; } )?
( BANG { autoGen = GrammarElement.AUTO_GEN_BANG; } )?
{ behavior.refRule(assignId, r2, label, args, autoGen); }
|
range [label]
|
terminal [label]
|
NOT_OP
( notTerminal[label]
| ebnf[label,true]
)
|
ebnf[label,false]
)
|
a:ACTION { behavior.refAction(a);}
|
p:SEMPRED { behavior.refSemPred(p);}
|
tree
;
tree :
lp:TREE_BEGIN
{ behavior.beginTree(lp.getLine()); }
rootNode
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -