Парсинг файлов проекта и пакета с использованием Gold Parser - требуется помощь с 'IdList'

Я работаю с движком Object Pascal Engine (от Роба ван ден Бринка), и кажется (за исключением нескольких незначительных и легко исправляемых ошибок) он работает для файлов модулей Delphi.

Однако возникают проблемы при разборе файлов Project (.dpr) и Package (.dpk); и проблема в основном сводится к различиям между тем, что "использует" может иметь в юнитах и ​​проектах (а также тем, что "содержит" может иметь в пакетах).

Позвольте мне привести простые примеры:

В модульном (.pas) файле предложение 'users' может выглядеть примерно так

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';

1 ответ

Решение

Я еще не пользовался пакетом 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's Builder рассматривает символы с открытой и закрытой фигурной скобкой { }, как особый случай, который, кажется, не позволяет использовать их как что-либо кроме окружения комментариев; Я не смог найти способ использовать их как часть правила грамматики. Мы надеемся, что результатом этого изменения будет то, что '{Form1}' просто игнорируется как комментарий, а примерная конструкция соответствует предыдущему варианту (" IN StringLiteral").

Кстати, Gold выглядит довольно неплохо, за исключением нескольких проблем, в том числе

  • ограничение, упомянутое в ReadMe, заключается в том, что он может обрабатывать только символы 0..127 и

  • его Parser Builder (v.5.2) жалуется при запуске с использованием прилагаемой к нему образцовой грамматики D7 (до предложенных мной изменений) о недопустимом символе начала и лексической ошибке в строке / состоянии 82. Возможно, я что-то пропустил...

Другие вопросы по тегам