ANTLR:修复左递归和相互左递归

时间:2013-02-04 13:49:58

标签: antlr mutual-recursion left-recursion

这是我正在研究的语法的一部分,用于开发解析器工具,这对我的研究非常重要。它在ANTLR IDE下给出了一个错误在eclipse中paraction, action, cspaction是相互左递归的。

我已经在网上搜索了一个解决方案,但还没有理解我会怎么做。由于这种语言是研究领域的标准,我没有改变语言语义细节的普遍性。

paraction : action | decl '\circspot' paraction;
action : schemaexp | command | INDEX | cspaction | action '['INDEX+ ':=' exp+']';

cspaction   : 'Skip'|'Stop'|'Chaos'|comm '\circthen' action | pred '&' action
        |action ';' action | action '\extchoice' action | action '\intchoice' action
        |action '\lpar' nsexp | csexp | nsexp '\rpar' action
        |action '\lpar' nsexp | nsexp '\rpar' action
        |action '\\' csexp | paraction '('exp+')' | '\circmu' INDEX '\circspot' action
        | ';' decl '\circspot' action | 'extchoice' decl '\circspot' action 
        | '\intchoice' decl '\circspot' action
        | '\lpar' csexp '\rpar' decl '\circspot' '\lpar' nsexp '\rpar' '\circspot' action 
        | '\interleave' decl '\circspot' '\lpar' nsexp '\rpar' action;

我实际上正在尝试为'Circus'创建一个语法文件,这是一种状态丰富的正式建模语言,它是一种称为Z的规范语言和一种称为CSP(Communicating Sequential Process)的流程建模语言的组合,所以是的这是一种现有的语言。它现在用于学术界,因为正在开发中的语言。我有一个语言的EBNF,我正在尝试将EBNF翻译成ANTLR中的语法。我设法让以下两条规则奏效。但是cspaction似乎很难。

paraction : (decl '\circspot' (paraction)+ | action)  ;
action  : ((schemaexp | command | N | cspaction)('[' IDENT+ ':=' exp+']')?)* ;

反斜杠是乳胶的一部分,现在可以省略,因为它们用作字符串。下面请找到马戏团的完整EBNF。它来自已发表的论文A Denotational Semantics for Circus

马戏团的全部EBNF - http://www.use.com/b1ad2df0609961615fff

1 个答案:

答案 0 :(得分:2)

我建议你使用ANTLR v4。以前版本的ANTLR v3不支持左递归(既不是间接递归也不是直接递归),但ANTLR v4 支持支持直接左递归。因此,在消除间接左递归规则并删除仅ParAction的生成(Decl '•')* Action之后,我最终得到了以下语法:

grammar Circus;

// parser rules
program
 : circus_par* EOF
 ;

circus_par
 : par
 | CHANNEL cdecl
 | CHANSET n '==' csexp
 | proc_decl
 ;

cdecl
 : simple_cdecl (';' simple_cdecl)*
 ;

simple_cdecl
 : n+ ':' exp
 | n+
 | '[' n+ ']' n+ ':' exp
 | schema_exp
 ;

proc_decl
 : PROCESS n '[' n+ ']' '^=' proc_def
 | PROCESS n '^=' proc_def
 ;

proc_def
 : decl '•' proc_def
 | decl '⊙' proc_def
 | proc
 ;

proc
 : BEGIN ppar* STATE schema_exp ppar* '•' action END
 | proc ';' proc
 | proc '□' proc
 | proc '⊓' proc
 | proc '|[' csexp ']|' proc
 | proc '|||' proc
 | proc '\\' proc
 | '(' decl '•' proc_def ')' '(' exp+ ')'
 | n '(' exp+ ')'
 | '(' decl '⊙' proc_def ')' '⌊' exp+ '⌋'
 | n '⌊' exp+ '⌋'
 | proc '[' n+ ':=' n+ ']'
 | n '[' exp+ ']'
 | ';' decl '•' proc
 | '□' decl '•' proc
 | '⊓' decl '•' proc 
 ;

ppar
 : par
 | n '^=' (decl '•')* action
 | NAMESET n '==' nsexp
 ;     

action
 : schema_exp
 | command
 | n
 | action '[' n+ ':=' exp+ ']'
 | SKIP
 | STOP
 | CHAOS
 | comm '→' action
 | pred '&' action
 | action ';' action
 | action '□' action
 | action '⊓' action
 | action '[|' nsexp
 | csexp
 | nsexp ']|' action
 | action '||[' nsexp
 | nsexp ']||' action
 | action '\\' csexp
 | (decl '•')+ action '(' exp+ ')'  
 | action '(' exp+ ')'  
 | 'μ' n '•' action
 | ';' decl '•' action
 | '□' decl '•' action
 | '⊓' decl '•' 
 | '|[' csexp ']|' decl '•' '|[' nsexp ']|' '•' action
 | '|||' decl '•' '|[' nsexp ']|' action
 ;

comm
 : n '[' exp+ ']' cparameter*
 | n cparameter*
 ;

cparameter
 : '?' n ':' pred
 | '?' n
 | '!' exp
 | '.' exp
 ;

command
 : n+ ':=' exp+
 | IF gactions FI
 | n+ ':' '[' pred ',' pred ']'
 | '[' pred ']'
 | '{' pred '}'
 | VAR decl '•' action
 | VAL decl '•' action
 | RES decl '•' action
 | VRES decl '•' action
 ;

gactions
 : pred '→' action '□' gactions
 | pred '→' action
 ;

n
 : ZID
 ;

par : 'TODO';
decl : 'TODO';
nsexp : 'TODO';
exp : 'TODO';
csexp : 'TODO';
schema_exp : 'TODO';
pred : 'TODO';

// lexer rules
CHANNEL : 'channel';
CHANSET : 'chanset';
PROCESS : 'process';
BEGIN : 'begin';
END : 'end';
STATE : 'state';
NAMESET : 'nameset';
SKIP : 'Skip';
STOP : 'Stop';
CHAOS : 'Chaos';
IF : 'if';
FI : 'fi';
VAL : 'val';
VAR : 'var';
RES : 'res';    
VRES : 'vres';

ZID : [a-zA-Z]+;

the one you posted a link to非常相似。

生成一个像这样的词法分析器和解析器:

java -cp antlr-4.0-complete.jar org.antlr.v4.Tool Circus.g4

请注意,您希望匹配文字反斜杠,您需要将其转义:

CIRCSPOT : '\\circspot';