用不完整的语法进行解析

时间:2011-08-26 11:12:40

标签: parsing antlr grammar parser-generator antlrworks

是否有任何常见的解决方案如何使用不完整的语法?在我的情况下,我只想检测Delphi(Pascal)文件中的方法,这意味着proceduresfunctions。以下第一次尝试正在进行中

    methods
      : ( procedure | function | . )+
      ;

但这是一个解决方案吗?还有更好的解决方案吗?是否可以通过动作停止解析(例如,在检测到implementation之后)。使用预处理器是否有意义?什么时候 - 如何?

2 个答案:

答案 0 :(得分:4)

如果你只是在寻找名字,那就像这样简单:

grammar PascalFuncProc;

parse
  :  (Procedure | Function)* EOF
  ;

Procedure
  :  'procedure' Spaces Identifier
  ;

Function
  :  'function' Spaces Identifier
  ;

Ignore
  :  (StrLiteral | Comment | .) {skip();}
  ;

fragment Spaces     : (' ' | '\t' | '\r' | '\n')+;
fragment Identifier : ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '_' | '0'..'9')*;
fragment StrLiteral : '\'' ~'\''* '\'';
fragment Comment    : '{' ~'}'* '}';

会做到这一点。请注意,我对Delhpi / Pascal不是很熟悉,因此我肯定会对StrLiteral和/或Comment进行调整,但这很容易解决。

从上面的语法生成的词法分析器只会生成两种类型的标记(ProcedureFunction s),其余的输入(字符串文字,注释或者如果没有匹配,单个字符:.)立即从词法分析器中丢弃(skip()方法)。

对于这样的输入:

some valid source
{ 
  function NotAFunction ...
}

procedure Proc
Begin
  ...
End;

procedure Func
Begin
  s = 'function NotAFunction!!!'
End;

创建了以下解析树:

enter image description here

答案 1 :(得分:4)

你问的是island grammars。这个概念是你为你所关心的语言部分(“岛”)定义了一个解析器,其中包含了该部分所需的所有经典标记,并且你定义了一个非常草率的解析器来跳过其余部分(“海洋”)其中嵌入岛屿)。这样做的一个常见技巧是定义相应的草率词法分析器,它们可以获取大量的东西(为了跳过HTML到嵌入式代码,你可以尝试跳过任何看起来像词法分析器中的脚本标记的东西,因为例子)。

ANTLR网站甚至discusses some related issues,但值得注意的是,ANTLR中包含了一些示例。我没有使用ANTLR的经验,因此我不知道这些具体信息有多么有用。

已经构建了许多工具,使用解析器来分析/转换代码(检查我的生物)我对岛屿grammmars的一般效用有点悲观。除非你的目标是使用解析岛做一些非常微不足道的事情,否则你需要直接或间接地收集它所使用的所有标识符的含义......并且很遗憾,对于你在海洋中定义的大多数标识符。所以恕我直言,你几乎必须解析海洋,以完成琐碎的任务。你也会有其他麻烦,确保你真的跳过岛上的东西;这几乎意味着你的海洋词法分析器已经知道空格,注释以及字符串的所有挑剔语法(这比现代语言看起来更难),以便正确地跳过它们。 YMMV。