为什么我的树语法含糊不清?

时间:2012-10-11 17:59:26

标签: antlr antlrworks

我有点困惑。我的语法运作良好,并且按照我的意愿匹配我的语言。最近,我在语法中添加了一些规则,在将新语法规则转换为树语法的过程中,我遇到了一些奇怪的错误。我得到的第一个错误是树语法不明确。

我收到的错误是:

[10:53:16] warning(200): ShiroDefinitionPass.g:129:17: 
Decision can match input such as "'subjunctive node'" using multiple alternatives: 5, 6

As a result, alternative(s) 6 were disabled for that input
[10:53:16] warning(200): ShiroDefinitionPass.g:129:17: 
Decision can match input such as "PORT_ASSIGNMENT" using multiple alternatives: 2, 6

还有大约10个类似的错误。

我不知道为什么树语法含糊不清。在添加sNode,subjunctDeclNodeProd,subjunctDecl和subjunctSelector规则之前没事。

我的语法是:

grammar Shiro;

options{
    language = Java;
    ASTLabelType=CommonTree;
    output=AST;
}

tokens{
    NEGATION;
    STATE_DECL;
    PORT_DECL;
    PORT_INIT;
    PORT_ASSIGNMENT;
    PORT_TAG;
    PATH;
    PORT_INDEX;
    EVAL_SELECT;
    SUBJ_SELECT;
    SUBJ_NODE_PROD;
    ACTIVATION;
    ACTIVATION_LIST;
    PRODUCES;
}

shiro   :   statement+
    ;   

statement
    :   nodestmt
    |   sNode 
    |   graphDecl
    |   statestmt
    |   collection
    |   view
    |   NEWLINE!
    ;

view    :   'view' IDENT mfName IDENT -> ^('view' IDENT mfName IDENT)
    ;

collection
    :   'collection' IDENT orderingFunc path 'begin' NEWLINE
            (collItem)+ NEWLINE?
        'end'
        -> ^('collection' IDENT orderingFunc path collItem+)
    ;

collItem:   IDENT -> IDENT
    ;

orderingFunc
    :   IDENT -> IDENT
    ;

statestmt
    :   'state' stateName 'begin' NEWLINE
        stateHeader
        'end' -> ^(STATE_DECL stateName stateHeader)
    ;

stateHeader
    :   (stateTimeStmt | stateCommentStmt | stateParentStmt | stateGraphStmt | activationPath | NEWLINE!)+  
    ;

stateTimeStmt
    :   'Time' time -> ^('Time' time)
    ;

stateCommentStmt
    :   'Comment' comment -> ^('Comment' comment)   
    ;

stateParentStmt
    :   'Parent' stateParent -> ^('Parent' stateParent)
    ;

stateGraphStmt
    :   'Graph' stateGraph -> ^('Graph' stateGraph)
    ;

stateName
    :   IDENT
    ;

time    :   STRING_LITERAL  
    ;

comment :   STRING_LITERAL
    ;

stateParent
    :   IDENT
    ;

stateGraph
    :   IDENT
    ;

activationPath
    :   l=activation ('.'^ (r=activation | activationList))*
    ;

activationList
    :   '<' activation (',' activation)* '>' -> ^(ACTIVATION_LIST activation+)
    ;

activation
    :   c=IDENT ('[' v=IDENT ']')? -> ^(ACTIVATION $c ($v)?)
    ;

graphDecl
    :   'graph' IDENT 'begin' NEWLINE
        graphLine+
        'end'
        -> ^('graph' IDENT graphLine+)
    ;

graphLine
    :   nodeProduction | portAssignment | NEWLINE!
    ;

nodeInternal
    :   (nodeProduction 
        | portAssignment 
        | portstmt 
        | nodestmt 
        | sNode 
        | NEWLINE!)+
    ;

nodestmt 
    :   'node'^ IDENT ('['! activeSelector ']'!)? 'begin'! NEWLINE!
        nodeInternal
        'end'!
    ;

sNode
:   'subjunctive node'^ IDENT '['! subjunctSelector ']'! 'begin'! NEWLINE!
        (subjunctDeclNodeProd | subjunctDecl | NEWLINE!)+
        'end'!
    ;

subjunctDeclNodeProd
    :   l=IDENT '->' r=IDENT 'begin' NEWLINE
        nodeInternal
        'end' -> ^(SUBJ_NODE_PROD $l $r nodeInternal )
    ;

subjunctDecl
    :   'subjunct'^ IDENT ('['! activeSelector ']'!)? 'begin'! NEWLINE!
        nodeInternal
        'end'!
    ;

subjunctSelector
    :   IDENT -> ^(SUBJ_SELECT IDENT)
    ;

activeSelector  
    :   IDENT -> ^(EVAL_SELECT IDENT)
    ;

nodeProduction
    :   path ('->'^ activationPath )+ NEWLINE!
    ;

portAssignment
    :   path '(' mfparams ')' NEWLINE -> ^(PORT_ASSIGNMENT path mfparams)
    ;   

portDecl
    :   portType portName mfName -> ^(PORT_DECL ^(PORT_TAG portType) portName mfName)
    ;

portDeclInit
    :   portType portName mfCall -> ^(PORT_INIT ^(PORT_TAG portType) portName mfCall)
    ;

portstmt    
    :   (portDecl | portDeclInit ) NEWLINE!
    ;   

portName 
    :   IDENT
    ;

portType:   'port'
    |   'eval'
    ;

mfCall  :   mfName '(' mfparams ')' -> ^(mfName mfparams)
    ;

mfName  :   IDENT
    ;

mfparams:   expression(',' expression)* -> expression+
    ;

// Path
path    :   (IDENT)('.' IDENT)*('[' pathIndex ']')? -> ^(PATH IDENT+ pathIndex?)
    ;

pathIndex
    :   portIndex -> ^(PORT_INDEX portIndex)
    ;

portIndex
    :   ( NUMBER |STRING_LITERAL )
    ;

// Expressions
term    :   path
    |   '(' expression ')' -> expression
    |   NUMBER
    |   STRING_LITERAL
    ;

unary   :   ('+'^ | '-'^)* term

    ;

mult    :   unary (('*'^ | '/'^ | '%'^) unary)*
    ;

add     
    :   mult (( '+'^ | '-'^ ) mult)*
    ;

expression
    :   add (( '|'^ ) add)*
    ;

// LEXEMES
STRING_LITERAL
    :   '"' .* '"'
    ;

NUMBER  :   DIGIT+ ('.'DIGIT+)?
    ;

IDENT   :   (LCLETTER | UCLETTER | DIGIT)(LCLETTER | UCLETTER | DIGIT|'_')*
    ;

COMMENT
        :       '//' ~('\n'|'\r')*  {$channel=HIDDEN;}
    |   '/*' ( options {greedy=false;} : . )* '*/' NEWLINE?{$channel=HIDDEN;}
        ;

WS
    :   (' ' | '\t' | '\f')+ {$channel = HIDDEN;}
    ;

NEWLINE :   '\r'? '\n'
    ;

fragment
LCLETTER 
    :   'a'..'z'
    ;

fragment
UCLETTER:   'A'..'Z'
    ;   

fragment
DIGIT   :   '0'..'9'
    ;

该部分的树语法如下:

tree grammar ShiroDefinitionPass;

options{
    tokenVocab=Shiro;
    ASTLabelType=CommonTree;
}

shiro
    :   statement+

    ;   

statement   
    :   nodestmt
    |   sNode
    |   graphDecl
    |   statestmt
    |   collection
    |   view
    ;

view    :   ^('view' IDENT mfName IDENT)
    ;

collection
    :   ^('collection' IDENT orderingFunc path collItem+)
    ;

collItem:   IDENT
    ;

orderingFunc
    :   IDENT
    ;

statestmt
    :   ^(STATE_DECL stateHeader)
    ;

stateHeader
    :   (stateTimeStmt | stateCommentStmt | stateParentStmt| stateGraphStmt | activation )+     
    ;

stateTimeStmt
    :   ^('Time' time)
    ;

stateCommentStmt
    :   ^('Comment' comment)    
    ;

stateParentStmt
    :   ^('Parent' stateParent)
    ;

stateGraphStmt
    :   ^('Graph' stateGraph)
    ;

stateName
    :   IDENT
    ;

time    :   STRING_LITERAL  
    ;

comment :   STRING_LITERAL
    ;

stateParent
    :   IDENT
    ;

stateGraph
    :   IDENT
    ;

activationPath
    :   l=activation ('.' (r=activation | activationList))*
    ;

activationList
    :   ^(ACTIVATION_LIST activation+)
    ;

activation
    :   ^(ACTIVATION IDENT IDENT?)
    ;

// Graph Declarations
graphDecl
    :   ^('graph' IDENT graphLine+)
    ;

graphLine
    :   nodeProduction
    |   portAssignmen
    ;
// End Graph declaration

nodeInternal
    :   (nodeProduction
        |portAssignment
        |portstmt
        |nodestmt
        |sNode )+
    ;

nodestmt
    :   ^('node' IDENT activeSelector? nodeInternal)    
    ;

sNode
    :   ^('subjunctive node' IDENT subjunctSelector (subjunctDeclNodeProd | subjunctDecl)*)
    ;

subjunctDeclNodeProd
    :   ^(SUBJ_NODE_PROD IDENT IDENT nodeInternal+ )
    ;

subjunctDecl
    :   ^('subjunct' IDENT activeSelector? nodeInternal )
    ;

subjunctSelector
    :   ^(SUBJ_SELECT IDENT)
    ;

activeSelector returns 
    :   ^(EVAL_SELECT IDENT)
    ;

nodeProduction
    :   ^('->' nodeProduction)
    |   path 
    ;

portAssignment
    :   ^(PORT_ASSIGNMENT path)  
    ;   

// Port Statement
portDecl
    :   ^(PORT_DECL ^(PORT_TAG portType) portName mfName) 
    ;

portDeclInit
    :   ^(PORT_INIT ^(PORT_TAG portType) portName mfCall)
    ;

portstmt    
    :   (portDecl | portDeclInit)
    ;   

portName
    :   IDENT 
    ;

portType returns 
    :   'port' | 'eval'
    ;


mfCall
    :   ^(mfName mfparams) 
    ;

mfName
    :   IDENT
    ;

mfparams  
    :   (exps=expression)+
    ;   

// Path
path
    :   ^(PATH (id=IDENT)+ (pathIndex)? )
    ;

pathIndex 
    :   ^(PORT_INDEX portIndex)
    ;

portIndex
    :   ( NUMBER 
        |STRING_LITERAL
        )
    ;

// Expressions
expression
    :   ^('+' op1=expression op2=expression) 
    |   ^('-' op1=expression op2=expression) 
    |   ^('*' op1=expression op2=expression) 
    |   ^('/' op1=expression op2=expression)
    |   ^('%' op1=expression op2=expression) 
    |   ^('|' op1=expression op2=expression)
    |   NUMBER 
    |   path
    ;

1 个答案:

答案 0 :(得分:2)

在您的树语法中,这是规则nodeInternal的声明:

  nodeInternal
    :  (nodeProduction
       |portAssignment
       |portstmt
       |nodestmt
       |sNode)+
    ;

以下是您对规则subjunctDeclNodeProd的声明:

   subjunctDeclNodeProd
    :   ^(SUBJ_NODE_PROD IDENT IDENT nodeInternal+ )
    ;

当处理subjunctDeclNodeProd时,ANTLR不知道如何处理这样的输入,有两个PATH个孩子:

^(SUBJ_NODE_PROD IDENT IDENT ^(PATH IDENT) ^(PATH IDENT))

它应该遵循规则nodeInternal一次并处理nodeProduction, nodeProduction还是应该遵循nodeInternal两次并且每次都处理nodeProduction

考虑在没有subjunctDeclNodeProd的情况下重写+

   subjunctDeclNodeProd
    :   ^(SUBJ_NODE_PROD IDENT IDENT nodeInternal)
    ;

我认为这会解决问题。