ANTLR解析分配

时间:2012-06-07 12:36:31

标签: parsing antlr antlr3

我想解析一些作业,我只关心整个作业。不是关于任务中的内容。 ':='指示作业。 (编辑:在任务之前和之后可能会有其他事情发生)

一些例子:

a := TRUE & FALSE;
c := a ? 3 : 5;
b := case 
          a : 1;
          !a : 0;
        esac;

目前,我在包含“案例”的作业与其他作业之间有所区别。对于简单的作业,我尝试了类似~('case' | 'esac' | ';')的内容,但后来antlr抱怨了无法匹配的令牌(如'=')。

assignment : 
   NAME ':='! expression ;

expression : 
    ( simple_expression | case_expression) ;


simple_expression : 
    ((OPERATOR | NAME) & ~('case' | 'esac'))+  ';'! ;

case_expression : 
    'case' .+ 'esac' ';'! ;

我尝试用以下内容替换,因为由于((OPERATOR | NAME) & ~('case' | 'esac'))+ ';'! ;,eclipse-interpreter似乎不喜欢'and'

   (~(OPERATOR | ~NAME | ('case' | 'esac')) |
    ~(~OPERATOR | NAME | ('case' | 'esac')) |
    ~(~OPERATOR | ~NAME | ('case' | 'esac')))  ';'!

但这不起作用。我得到了

  

“错误(139):/ AntlrTutorial/src/foo/NusmvInput.g:78:5:设置补全为空| --->〜(〜操作者|〜名称|('案例'|'esac' )))EOC!;“

我该如何解析它?

1 个答案:

答案 0 :(得分:2)

这里有一些问题:

  • 你在语法中使用&,而它周围应该有引号:'&'
  • 除非您确切知道自己在做什么,否则请不要在解析器规则中使用~.(尤其不是.+!):仅在词法规则中使用它们; < / LI>
  • 创建词法分析器规则,而不是在解析器规则中定义'case''esac'(如果没有其他词法规则可能匹配,则在解析器规则中使用文字标记是安全的,但是{{1}和'case' 看起来很像'esac' 它们最终会出现在你的AST中,在这种情况下最好自己明确定义它们词法分析程序)

这是一个快速演示:

NAME

将解析您的输入:

grammar T;

options {
  output=AST;
}

tokens {
  ROOT;
  CASES;
  CASE;
}

parse
 : (assignment SCOL)* EOF -> ^(ROOT assignment*)
 ;

assignment 
 : NAME ASSIGN^ expression 
 ;

expression
 : ternary_expression
 ;

ternary_expression
 : or_expression (QMARK^ ternary_expression COL! ternary_expression)?
 ;

or_expression
 : unary_expression ((AND | OR)^ unary_expression)*
 ;

unary_expression
 : NOT^ atom
 | atom
 ;

atom
 : TRUE
 | FALSE
 | NUMBER
 | NAME
 | CASE single_case+ ESAC -> ^(CASES single_case+)
 | '(' expression ')'     -> expression
 ;

single_case
 : expression COL expression SCOL -> ^(CASE expression expression)
 ;

TRUE   : 'TRUE';
FALSE  : 'FALSE';
CASE   : 'case';
ESAC   : 'esac';
ASSIGN : ':='; 
AND    : '&';
OR     : '|';
NOT    : '!';
QMARK  : '?';
COL    : ':';
SCOL   : ';';
NAME   : ('a'..'z' | 'A'..'Z')+;
NUMBER : ('0'..'9')+;
SPACE  : (' ' | '\t' | '\r' | '\n')+ {skip();};

如下:

enter image description here