3

我正在涉足Object Pascal Engine(由 Rob van den Brink 编写),它似乎(除了一些小且易于纠正的错误)适用于 Delphi 单元文件。

但是,它在解析项目 ( .dpr) 和包 ( .dpk) 文件时存在问题;这个问题基本上归结为单元和项目中“使用”的东西之间的差异(以及包中的“包含”子句)。

让我举个简单的例子:

在单元 (.pas) 文件中,“uses”子句可以是这样的

uses
  Windows,
  Messages,
  SysUtils,
  Variants,
  Classes,
  Graphics,
  Controls,
  Forms,
  Dialogs,
  StdCtrls,
  ExtCtrls,
  ComCtrls;

而在项目 (.dpr) 文件中

uses
  Forms,
  UnitDemoMain in 'UnitDemoMain.pas' {Form1},
  SomeUnit in '..\SomeUnit.pas',
  SomeOtherUnit;

然而,相同的功能(以“包含”的名义)出现为:

contains
  OneUnit in 'OneUnit.pas',
  AnotherUnit in '..\AnotherUnit.pas';

我拥有的语法文件(来自上面的链接)的问题是它只处理最简单的情况(即单元文件中出现“使用”的方式),并为其他人抛出错误。

我猜它归结为语法文件中如何定义“IdList”,即:

<IdList> ::= <IdList> ',' <RefId>
| <RefId>

那么,我的问题是:如何更改此定义,以便它可以处理其他替代方案(如 Project 和 Pacckage 文件中所示),即:

UnitDemoMain in 'UnitDemoMain.pas' {Form1},
OneUnit in 'OneUnit.pas';
4

1 回答 1

2

我自己还没有用过Gold包,但是我用过不少Yacc;语法布局略有不同,但原理相同。

对于初学者,我会尝试如下修改 Delphi 语法:

改变

<UsesClause>        ::= USES <IdList> ';'
              | SynError

<UsesClause>        ::= USES <UnitList> ';'
              | SynError

并添加

<UnitList>      ::= <UnitList> ',' <UnitRef>
              | <UnitRef>

<UnitRef>       ::= <RefID>
              | <RefID> IN <StringLiteral>
!                 | <RefID> in <StringLiteral> Comment Start <RefID> Comment End

我用感叹号注释掉的那行最初是为了在你的例子中处理这个结构:

  UnitDemoMain in 'UnitDemoMain.pas' {Form1},

但是,Gold 的 Builder 似乎将左大括号和右大括号字符 { } 视为一种特殊情况,这似乎可以防止它们被用作除了围绕注释之外的任何东西;我一直无法找到将它们用作语法规则的一部分的方法。这种更改的结果应该是 '{Form1}' 被简单地忽略为注释,而示例构造匹配先前的变体(“<RefID> IN StringLiteral”)。

Fwiw,Gold 看起来相当不错,除了一些问题,包括

  • 自述文件中提到的限制,它只能处理字符 0..127 和

  • 它的 Parser Builder (v.5.2) 在使用它附带的 D7 示例语法运行时(在我建议的更改之前)抱怨无效的开始符号和第 82 行/状态的词法错误。也许我错过了一些东西......

于 2016-03-08T17:40:00.297 回答