Повторите определенную функциональность во многих различных данных

Я пишу компилятор на Haskell, поэтому у нас есть много (или, по крайней мере, мне кажется, много) dataи конструкторы, такие как следующие:

data DataType
    = Int | Float | Bool | Char | Range | Type
    | String Width
    | Record (Lexeme Identifier) (Seq Field) Width
    | Union  (Lexeme Identifier) (Seq Field) Width
    | Array   (Lexeme DataType) (Lexeme Expression) Width
    | UserDef (Lexeme Identifier)
    | Void | TypeError  -- For compiler use


data Statement
    -- Language
    = StNoop
    | StAssign (Lexeme Access) (Lexeme Expression)
    -- Definitions
    | StDeclaration      (Lexeme Declaration)
    | StDeclarationList  (DeclarationList Expression)
    | StStructDefinition (Lexeme DataType)
    -- Functions
    | StReturn        (Lexeme Expression)
    | StFunctionDef   (Lexeme Declaration) (Seq (Lexeme DataType))
    | StFunctionImp   (Lexeme Identifier)  (Seq (Lexeme Identifier)) StBlock
    | StProcedureCall (Lexeme Identifier)  (Seq (Lexeme Expression))
    -- I/O
    | StRead  (Seq (Lexeme Access))
    | StPrint (Seq (Lexeme Expression))
    -- Conditional
    | StIf   (Lexeme Expression) StBlock StBlock
    | StCase (Lexeme Expression) (Seq (Lexeme When))      StBlock
    -- Loops
    | StLoop     StBlock (Lexeme Expression) StBlock
    | StFor      (Lexeme Identifier) (Lexeme Expression)  StBlock
    | StBreak
    | StContinue

И многое другое Вы могли заметить повторение Lexeme a во многих из конструкторов.

Лексема следующая data

type Position = (Int, Int)

data Lexeme a = Lex
    { lexInfo :: a
    , lexPosn :: Position
    }

Так что это работает для хранения информации о Position элемента в файле программы, для сообщения об ошибках и предупреждениях.

Есть ли более простой способ справиться с сохранением информацииPosition проблема?

2 ответа

Решение

Можно двигаться "вверх" Lexeme приложение:

type Access = Lexeme Access'
data Access' = ...
type Expression = Lexeme Expression'
data Expression' = ...
-- etc.
data Statement
    -- Language
    = StNoop
    | StAssign Access Expression
    -- Definitions
    | StDeclaration      Declaration
    | StDeclarationList  (DeclarationList Expression')  -- maybe you can also use Expression here?
    | StStructDefinition DataType
    ...

Таким образом, вы применяете Lexeme один раз каждое определение типа, а не один раз каждый тип использования.

Я привык видеть другой конструктор, который может использоваться для хранения лексической информации:

data Expression = ... all the old Exprs
                | ExprPos Position Expression

data Declaration = ... decls ...
                 | DeclPos Position Declaration

Теперь в вашем Statement и другие типы данных вместо таких вещей, как:

| StFor      (Lexeme Identifier) (Lexeme Expression)  StBlock

у тебя есть:

| StFor      Identifier Expression StBlock
Другие вопросы по тегам