I'm writing a compiler in Haskell, so we have a lot (or at least it seems like a lot for me) of data
s and constructors, such as the followings:
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
And many more. You may have noticed the repeating Lexeme a
in many of the constructors.
Lexeme is the following data
type Position = (Int, Int)
data Lexeme a = Lex
{ lexInfo :: a
, lexPosn :: Position
}
So it works for keeping the information of the Position
of an element in the program's file, for reporting errors and warnings.
Position
problem?I'm accustomed to seeing another constructor that can be used optionally to hold lexical information:
data Expression = ... all the old Exprs
| ExprPos Position Expression
data Declaration = ... decls ...
| DeclPos Position Declaration
Now in your Statement
and other data types instead of things like:
| StFor (Lexeme Identifier) (Lexeme Expression) StBlock
you have:
| StFor Identifier Expression StBlock
One could move "up" the Lexeme
application:
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
...
In this way you apply Lexeme
once every type definition, instead of once every type use.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With