Skip to content

Commit

Permalink
[add] Parser State and utils haddock documentation comments
Browse files Browse the repository at this point in the history
  • Loading branch information
RenzoMaggiori committed Jan 19, 2025
1 parent bbd9ac0 commit 97e36e1
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 2 deletions.
19 changes: 17 additions & 2 deletions lib/Ast/Parser/State.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,23 @@ module Ast.Parser.State where
import qualified Ast.Types as AT
import qualified Data.Set as Set

-- | Represents the state of type definitions in the parser.
type TypeState = [(String, AT.Type)]

-- | Represents the state of variable definitions in the parser.
type VarState = [(String, AT.Type)]

-- | Tracks preprocessor-specific information, such as visited imports and import depth.
data PreProcessorState = PreProcessorState
{ visitedImports :: Set.Set String,
importDepth :: Int
}
deriving (Show, Eq)

-- | Represents the stack of deferred expressions, grouped by scope.
type DeferState = [[AT.Expr]]

-- | The complete state of the parser, including types, variables, preprocessor state, and deferred expressions.
data ParserState = ParserState
{ typeState :: TypeState,
varState :: VarState,
Expand All @@ -23,6 +28,7 @@ data ParserState = ParserState
}
deriving (Show, Eq)

-- | The initial state of the parser.
parserState :: ParserState
parserState = ParserState [] [] (PreProcessorState Set.empty 0) []

Expand All @@ -35,24 +41,33 @@ insertType name t s = s {typeState = (name, t) : typeState s}
lookupType :: String -> ParserState -> Maybe AT.Type
lookupType name (ParserState {typeState = types}) = lookup name types

-- | Inserts a variable into the environment.
-- If the variable already exists, it overwrites it.
insertVar :: String -> AT.Type -> ParserState -> ParserState
insertVar name t s = s {varState = (name, t) : varState s}

-- | Looks up a variable in the environment by its name.
-- Returns `Nothing` if the variable is not found.
lookupVar :: String -> ParserState -> Maybe AT.Type
lookupVar name (ParserState {varState = vars}) = lookup name vars

-- | Marks an import as visited by adding it to the set of visited imports.
insertImport :: String -> ParserState -> ParserState
insertImport i s =
s {preProcessorState = (preProcessorState s) {visitedImports = Set.insert i $ visitedImports . preProcessorState $ s}}

-- | Checks if a file has already been imported.
-- Returns `True` if the file is in the set of visited imports.
lookupImport :: String -> ParserState -> Bool
lookupImport i (ParserState {preProcessorState = PreProcessorState {visitedImports = vi}})
| Set.member i vi = True
| otherwise = False

-- | Sets the depth of nested imports in the preprocessor state.
setImportDepth :: Int -> ParserState -> ParserState
setImportDepth d s = s {preProcessorState = (preProcessorState s) {importDepth = d}}

-- | Gets the current depth of nested imports from the preprocessor state.
getImportDepth :: ParserState -> Int
getImportDepth (ParserState {preProcessorState = PreProcessorState {importDepth = d}}) = d

Expand All @@ -71,5 +86,5 @@ pushScope s@(ParserState {deferState = ds}) = s {deferState = [] : ds}
popScope :: ParserState -> ([AT.Expr], ParserState)
popScope s@(ParserState {deferState = ds}) =
case ds of
[] -> ([], s) -- No deferred expressions to pop.
(top : rest) -> (top, s {deferState = rest}) -- Pop the top stack and update state.
[] -> ([], s)
(top : rest) -> (top, s {deferState = rest})
14 changes: 14 additions & 0 deletions lib/Ast/Parser/Utils.hs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import qualified Text.Megaparsec.Pos as MP
-- | A type alias for the parser, based on `Parsec` with `Void` error type and `String` input.
type Parser = M.ParsecT ParseErrorCustom String (S.StateT PS.ParserState IO)

-- | Custom error types for the parser.
data ParseErrorCustom
= UnknownType String
| InvalidFunctionType String AT.Type
Expand Down Expand Up @@ -55,26 +56,32 @@ parseSrcLoc = do
(MP.SourcePos {MP.sourceName = _sourceName, MP.sourceLine = _sourceLine, MP.sourceColumn = _sourceColumn}) <- M.getSourcePos
return $ AT.SrcLoc {AT.srcFile = _sourceName, AT.srcLine = MP.unPos _sourceLine, AT.srcCol = MP.unPos _sourceColumn}

-- | Creates a prefix operator parser.
prefix :: String -> (AT.SrcLoc -> AT.Expr -> AT.Expr) -> CE.Operator Parser AT.Expr
prefix name f = CE.Prefix (f <$> (parseSrcLoc <* symbol name))

-- | Creates a postfix operator parser.
postfix :: String -> (AT.SrcLoc -> AT.Expr -> AT.Expr) -> CE.Operator Parser AT.Expr
postfix name f = CE.Postfix (f <$> (parseSrcLoc <* symbol name))

-- | Helper functions to define operators
binary :: String -> (AT.SrcLoc -> AT.Expr -> AT.Expr -> AT.Expr) -> CE.Operator Parser AT.Expr
binary name f = CE.InfixL (f <$> (parseSrcLoc <* symbol name))

-- | Parses a boolean value (`true` or `false`).
-- Returns a `Bool`.
parseBool :: Parser Bool
parseBool = True <$ MC.string "true" M.<|> False <$ MC.string "false"

-- | Parses a character in a string literal, supporting escape sequences.
parseStringChar :: Parser Char
parseStringChar =
M.choice
[ parseEscapeSequence,
M.noneOf ['"', '\\']
]

-- | Parses an escape sequence in a string literal (e.g., `\n`, `\t`, `\xFF`).
parseEscapeSequence :: Parser Char
parseEscapeSequence =
MC.char '\\'
Expand All @@ -94,26 +101,33 @@ parseEscapeSequence =
parseOctalEscape
]

-- | Parses a hexadecimal escape sequence (e.g., `\xFF`).
parseHexEscape :: Parser Char
parseHexEscape = do
_ <- MC.char 'x'
digits <- M.count 2 hexDigit
return $ C.chr $ read ("0x" ++ digits)

-- | Parses an octal escape sequence (e.g., `\077`).
parseOctalEscape :: Parser Char
parseOctalEscape = do
digits <- M.count 3 octalDigit
return $ C.chr $ read ("0o" ++ digits)

-- | Parses a hexadecimal digit (`0-9`, `a-f`, `A-F`).
hexDigit :: Parser Char
hexDigit = M.oneOf $ ['0' .. '9'] ++ ['a' .. 'f'] ++ ['A' .. 'F']

-- | Parses an octal digit (`0-7`).
octalDigit :: Parser Char
octalDigit = M.oneOf ['0' .. '7']

-- | A default `SrcLoc` for normalization.
normalizeLoc :: AT.SrcLoc
normalizeLoc = AT.SrcLoc "" 0 0

-- | Normalizes expressions by resetting their source locations.
-- Ensures consistent formatting and comparison of expressions.
normalizeExpr :: AT.Expr -> AT.Expr
normalizeExpr (AT.Lit _ lit) = AT.Lit normalizeLoc lit
normalizeExpr (AT.Var _ name t) = AT.Var normalizeLoc name t
Expand Down

0 comments on commit 97e36e1

Please # to comment.