Повторите определенную функциональность во многих различных данных
Я пишу компилятор на 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