wiki:ru/uaflex

Version 1 (modified by vadim.godunko, 9 years ago) ( diff )

--

uaflex - генератор синтаксических сканеров

Требования к архитектуре генерируемого кода:

  • поддержка start condition;
  • поддержка traling condition;
  • поддержка неблокирующих потоков ("посимвольное" чтение с возможностью приостановки при отсутствии данных с возвратом управления и продолжения обработки в последующем);
  • поддержка "возврата" по потоку на несколько символов и переразбор символов после изменения start condition. Для XML достаточно поддержки четырёх символов;
  • отслеживание положения в потоке в виде счётчиков: символ в потоке, строка/позиция в строке, и т.д.;
  • доступ к тексту распознанного токена;
  • "интерактивный" режим (без заглядывания на один символ вперёд);
  • легкость в построении "вложенных" сканеров, когда при разборе одного потока возникает необходимость обработки другого потока с возвратом к предыдущему.

Возможные оптимизации:

  • не сохранять поступающие символы в некоторых start condition.

Варианты API

Интерфейс источника данных

Интерфейс источника данных может выглядеть так:

   type Source is limited interface;

   type Status_Kind is (Success, End_Of_Input, End_Of_Data, Error);

   not overriding procedure Get_Next
    (Self   : not null access Source;
     Code   : out Code_Point;
     Status : out Status_Kind) is abstract;

или же можно использовать некоторые значения Code_Unit_32 за пределами значений Code_Point для представления ошибок и преобразовать процедуру в функцию:

   End_Of_Input : constant Code_Unit_32 := 16#FFFFFFFD#;
   End_Of_Data  : constant Code_Unit_32 := 16#FFFFFFFE#;
   Error        : constant Code_Unit_32 := 16#FFFFFFFF#;

   type Source is limited interface;

   not overriding function Get_Next
    (Self : not null access Source) return Code_Unit_32 is abstract;

OOP стиль pull сканера

Сканер вызывает подпрограммы для каждого распознанного токена. Каждая подпрограмма является диспетчеризируемой операцией некоторого интерфейсного типа и возвращает признаки:

  • необходимость вернуть токен;
  • возвращаемый токен.

Три значения токена предопределены:

  • достигнут конец данных (End_Of_Input);
  • нет доступных данных (End_Of_Data);
  • ошибка (Error).

Интерфейсный тип обработчика может выглядеть так:

   type Handler is limited interface;

   not overriding procedure On_Token
    (Self    : not null access Handler;
     Scanner : not null access Scanner'Class;
     Token   : out Token;
     Done    : out Boolean) is abstract;

Тэговый тип сканера:

   type Token is (..., End_Of_Input, End_Of_Data, Error);

   type Start_Condition is (Initial, ...);

   type Scanner is tagged limited private;

   procedure Set_Source
    (Self : in out Scanner'Class; Source : not null Source_Access);

   procedure Set_Start_Condition
    (Self : in out Scanner'Class; Condition : Start_Condition);

   function Get_Start_Condition
    (Self : Scanner'Class) return Start_Condition;

   procedure Get_Token (Self : in out Scanner'Class; Token : out Token);

   procedure Move_Back (Self : in out Scanner'Class; Count : Positive);

   function Get_Text
    (Self : Scanner'Class) return League.Strings.Universal_String;
Note: See TracWiki for help on using the wiki.