5

有没有常见的解决方案如何使用不完整的语法?就我而言,我只想检测 Delphi (Pascal) 文件中的方法,这意味着proceduresfunctions. 以下第一次尝试正在工作

    methods
      : ( procedure | function | . )+
      ;

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

4

2 回答 2

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 不是很熟悉,所以我肯定会搞砸StrLiterals 和/或Comments,但这很容易解决。

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

对于这样的输入:

some valid source
{ 
  function NotAFunction ...
}

procedure Proc
Begin
  ...
End;

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

创建以下解析树:

在此处输入图像描述

于 2011-08-26T13:09:57.523 回答
4

What you asking about are called island grammars. The notion is that you define a parser for the part of the language you care about (the "island") with all the classic tokenization needed for that part, and that you define an extremely sloppy parser to skip the rest (the "ocean" in which the island is embedded). One common trick to doing this is to define correspondingly sloppy lexers, that pick up vast amounts of stuff (to skip past HTML to embedded code, you can try to skip past anything that doesn't look like a script tag in the lexer, for example).

The ANTLR site even discusses some related issues but notably says there are examples included with ANTLR. I have no experience with ANTLR so I don't know how useful this specific information is.

在构建了许多使用解析器来分析/转换代码的工具(查看我的简历)之后,我对岛文法的一般效用有点悲观。除非您的目标是对已解析的岛做一些非常微不足道的事情,否则您将需要收集它直接或间接使用的所有标识符的含义……不幸的是,其中大多数是在海洋中为您定义的。所以恕我直言,您几乎也必须解析海洋才能完成琐碎的任务。你也会遇到其他麻烦,确保你真的跳过岛上的东西;这几乎意味着您的海洋词法分析器了解空格、注释和字符串的所有挑剔语法(这比现代语言看起来更难),因此可以正确跳过这些语法。YMMV。

于 2011-08-26T13:59:18.093 回答