ANTLR解析分配 [英] ANTLR parse assignments

查看:94
本文介绍了ANTLR解析分配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想分析一些作业,其中我只关心整个作业.与作业中的内容无关.分配由':='指示. (在分配作业前后,可能还会有其他事情发生)

I want to parse some assignments, where I only care about the assignment as a whole. Not about whats inside the assignment. An assignment is indiciated by ':='. ( Before and after the assignments other things may come)

一些例子:

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

目前,我在包含案例"的作业和其他作业之间进行区别.对于简单的任务,我尝试了类似~('case' | 'esac' | ';')的方法,但是随后antlr抱怨令牌不匹配(例如'=').

Currently I make a difference between assignments containing a 'case' and other assignments. For simple assignments I tried something like ~('case' | 'esac' | ';') but then antlr complained about unmatched tokens (like '=').

assignment : 
   NAME ':='! expression ;

expression : 
    ( simple_expression | case_expression) ;


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

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

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

I tried replacing with the following, because the eclipse-interpreter did not seem to like the ((OPERATOR | NAME) & ~('case' | 'esac'))+ ';'! ; because of the 'and'.

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

但这不起作用.我得到

错误(139):/AntlrTutorial/src/foo/NusmvInput.g:78:5:设置补码为空| --->〜(〜OPERATOR |〜NAME |('case'|'esac') ))EOC!;"

"error(139): /AntlrTutorial/src/foo/NusmvInput.g:78:5: set complement is empty |---> ~(~OPERATOR | ~NAME | ('case' | 'esac'))) EOC! ;"

如何解析?

推荐答案

这里有些错误:

  • 您在语法中使用了&,但它周围应带有引号:'&'
  • 除非您确切地知道自己在做什么,否则请不要在解析器规则中使用~.(尤其是.+!):仅在词法分析器规则中使用它们;
  • 创建词法分析器规则,而不是在解析器规则中定义'case''esac'(如果没有其他词法分析器规则可能匹配,则在解析器规则中使用文字标记是安全的,但是'case''esac' look 很像NAME ,它们可能会出现在您的AST中,在这种情况下,最好在词法分析器中自己明确定义它们)
  • you're using & in your grammar while it should be with quotes around it: '&'
  • unless you know exactly what you're doing, don't use ~ and . (especially not .+ !) inside parser rules: use them in lexer rules only;
  • create lexer rules instead of defining 'case' and 'esac' in your parser rules (it's safe to use literal tokens in your parser rules if no other lexer rule can potentially match is, but 'case' and 'esac' look a lot like NAME and they could end up in your AST in which case it's better to explicitly define them yourself in the lexer)

这是一个快速演示:

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();};

这将解析您的输入:

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

如下:

这篇关于ANTLR解析分配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆