record-syntax-0.1.0.0: library/Record/Syntax.hs
module Record.Syntax where
import Record.Syntax.Prelude
import Record.Syntax.Shared
import qualified Record.Syntax.LevelReifier as LevelReifier
import qualified Record.Syntax.Position as Position
import qualified Record.Syntax.Parser as Parser
import qualified Record.Syntax.Renderer as Renderer
processModule :: Text -> Either Error TextBuilder
processModule input =
join $ runParser pass1Parser
where
runParser p =
Parser.run p input
pass1Parser =
liftA2 mappend <$> fmap pure head <*> body
where
head =
flip fmap Parser.moduleHead $ \(output, t) -> output <> "import qualified Record" <> ending t
where
ending =
\case
Parser.LineType_Space -> ""
Parser.LineType_Comment -> " "
Parser.LineType_Import -> "; "
Parser.LineType_Other -> "\n"
body =
do
offset <- Parser.position
forest <- Parser.total $ Parser.extendableSyntaxForest Parser.unparsedExtensionLexeme
return $ processExtensionForest Level_Decl forest
process :: Level -> Text -> Either Error TextBuilder
process level input =
do
forest <- Parser.run parser $ input
processExtensionForest level forest
where
parser =
Parser.extendableSyntaxForest Parser.unparsedExtensionLexeme
processExtensionForest :: Level -> ExtendableSyntaxForest TextBuilder -> Either Error TextBuilder
processExtensionForest level forest =
do
levels <- reifyLevels level forest
forest' <- zipTraversableWithM (\a b -> processExtension b (convert a)) forest levels
return $ Renderer.extendableSyntaxForest id forest'
where
reifyLevels level =
LevelReifier.reify level . convert .
Renderer.extendableSyntaxForest (const marker)
processExtension :: Level -> Text -> Either Error TextBuilder
processExtension level input =
join $ Parser.run (parser level) input
where
parser =
\case
Level_Exp -> fmap processExtensionExp Parser.extensionExp
Level_Type -> fmap processExtensionType Parser.extensionType
processExtensionExp :: ExtensionExp (Position, TextBuilder) -> Either Error TextBuilder
processExtensionExp =
\case
ExtensionExp_Record x -> processRecordExp x
ExtensionExp_Label x -> pure $ Renderer.labelExp x
processRecordExp :: RecordExp (Position, TextBuilder) -> Either Error TextBuilder
processRecordExp =
fmap (Renderer.recordExp id) .
traverse (\(p, i) -> offsetResult p $ process Level_Exp $ convert i)
processExtensionType :: ExtensionType -> Either Error TextBuilder
processExtensionType =
\case
ExtensionType_Record x -> pure $ Renderer.recordType x
offsetResult :: Position -> Either Error a -> Either Error a
offsetResult p =
either (Left . (\f (a, b) -> (f a, b)) (Position.add p)) Right