delphipascalgold-parser

Parsing Project and Package files using Gold Parser --help needed with 'IdList'


I am dabbling with the Object Pascal Engine (by Rob van den Brink) and it seems (except for a few minor and easily correctable errors) it works for Delphi unit files.

However, it has problems parsing Project (.dpr) and Package (.dpk) files; and the issue basically boils down to the differences between the stuff that 'uses' can have in units and projects (as well as what 'contains' clause can have in packages).

Let me give simple examples:

In a unit (.pas) file, the 'uses' clause can be something like this

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

whereas, in a Project (.dpr) file

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

Yet, the same functionality (in the name of 'contains') occurs as:

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

The problem with the grammar file I have (from the above link) is that it only handles the most simple case (i.e. the way 'uses' occurs in unit files), and throws error for others.

I am guessing it boils down how 'IdList' is defined in the grammar file, which is this:

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

My question, then, is: How do I alter this definition, so that it can handle other alternatives (as seen in Project and Pacckage files), i.e.:

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

Solution

  • I haven't used the Gold package myself yet, but I have used Yacc quite a bit; that has a slightly different grammar layout but the principle is the same.

    For starters I would try modifying the Delphi grammar as follows:

    Change

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

    to

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

    and add

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

    The line which I've commented out using the exclamation mark was initially intended to handle this construct in your example:

      UnitDemoMain in 'UnitDemoMain.pas' {Form1},
    

    However, it seems that Gold's Builder treats the open- and close-curly-brace characters, { }, as a special case which seems to prevent them being used as anything other than to surround comments; I've been unable to find a way of using them as part of a grammar rule. The result of this change should hopefully be that '{Form1}' is simply ignored as a comment, and the example construct matches the previous variant ("<RefID> IN StringLiteral") instead.

    Fwiw, Gold looks quite a nice package, except for a few problems including