Struct Parsing continued, ditched multiple-errors support

This commit is contained in:
VegOwOtenks 2025-01-01 23:04:00 +01:00
parent 0adef12173
commit 9f2fad1507
10 changed files with 70 additions and 48 deletions

View file

@ -21,6 +21,7 @@ description: Please see the README on GitHub at <https://github.com/gith
dependencies: dependencies:
- base >= 4.7 && < 5 - base >= 4.7 && < 5
- containers
- parsec - parsec
ghc-options: ghc-options:

View file

@ -1,11 +0,0 @@
module Data.String.Ubc.Parse.Error.StructError
( StructError(..)
)
where
import Text.Parsec (SourcePos)
data StructError =
MissingNameError SourcePos
| MissingBraceError (Either SourcePos SourcePos)
-- the either branch indicates which one is missing

View file

@ -2,6 +2,8 @@ module Data.String.Ubc.Parse.ParserState
( ParserState(..) ( ParserState(..)
, initialState , initialState
, pushScope , pushScope
, popScope
, modifyScope
) )
where where
@ -16,3 +18,9 @@ initialState = ParserState []
pushScope :: Scope -> ParserState -> ParserState pushScope :: Scope -> ParserState -> ParserState
pushScope scope oldState@ParserState{scopes = oldScopes} = oldState{scopes = (scope : oldScopes)} pushScope scope oldState@ParserState{scopes = oldScopes} = oldState{scopes = (scope : oldScopes)}
popScope :: ParserState -> (ParserState, Scope)
popScope oldState@ParserState{scopes = (topScope:restScopes)} = (oldState{scopes = restScopes}, topScope)
modifyScope :: (Scope -> Scope) -> ParserState -> ParserState
modifyScope f oldState@ParserState{scopes = (topScope:restScopes)} = oldState{scopes = (f topScope : restScopes)}

View file

@ -1,5 +1,6 @@
module Data.String.Ubc.Parse.Scope module Data.String.Ubc.Parse.Scope
( Scope(..) ( Scope(..)
, expectScopeStruct
) )
where where
@ -9,3 +10,6 @@ import Data.String.Ubc.Parse.StructScope (StructScope)
data Scope = data Scope =
ScopeFile FileScope ScopeFile FileScope
| ScopeStruct StructScope | ScopeStruct StructScope
expectScopeStruct (ScopeStruct s) = s
expectScopeStruct _ = error "Internal Error: Top Scope is not Scope Struct"

View file

@ -4,54 +4,69 @@ module Data.String.Ubc.Parse.Struct
) )
where where
import Control.Arrow
import Text.Parsec import Text.Parsec
import Data.String.Ubc.Parse.StructVariable (StructVariable) import Data.Map (Map)
import Data.String.Ubc.Parse.StructVariable (StructVariable(StructVariable))
import Data.String.Ubc.Parse.ParserState (ParserState) import Data.String.Ubc.Parse.ParserState (ParserState)
import Data.String.Ubc.Parse.Error.StructError (StructError)
import Data.String.Ubc.Parse.StructScope (StructScope(..)) import Data.String.Ubc.Parse.StructScope (StructScope(..))
import Data.String.Ubc.Parse.Scope (Scope(..)) import Data.String.Ubc.Parse.Scope (Scope(..))
import qualified Data.String.Ubc.Parse.Language as UbcLanguage import qualified Data.String.Ubc.Parse.Language as UbcLanguage
import qualified Data.String.Ubc.Parse.Error.StructError as StructError
import qualified Data.String.Ubc.Parse.StructScope as StructScope import qualified Data.String.Ubc.Parse.StructScope as StructScope
import qualified Data.String.Ubc.Parse.ParserState as ParserState import qualified Data.String.Ubc.Parse.ParserState as ParserState
import qualified Data.String.Ubc.Parse.Scope as Scope
import qualified Data.Map as Map
data Struct = Struct data Struct = Struct
{ name :: String { name :: String
, memberVariables :: [StructVariable] , memberVariables :: Map String StructVariable
} }
deriving (Show)
parseStruct :: Monad m => ParsecT String ParserState m (Either StructError Struct) parseStruct :: Monad m => ParsecT String ParserState m Struct
parseStruct = do parseStruct = do
_ <- UbcLanguage.reserved "struct" _ <- UbcLanguage.reserved "struct"
structName <- choice structIdentifier <- UbcLanguage.identifier
[ UbcLanguage.identifier >>= return . Right
, getPosition >>= return . Left . StructError.MissingNameError
]
let structScope = StructScope let structScope = StructScope
{ structName = either (const Nothing) (Just) structName { structName = structIdentifier
, errors = [] , variables = Map.empty
} }
updateState (ParserState.pushScope . ScopeStruct $ structScope) modifyState (ParserState.pushScope . ScopeStruct $ structScope)
openingBrace <- choice _ <- UbcLanguage.braces (many structMember)
[ UbcLanguage.symbol "{" >>= return . Right
, getPosition >>= return . Left . StructError.MissingBraceError . Left
]
_ <- structMember `manyTill` (lookAhead $ choice [ eof, UbcLanguage.symbol "}" ]) structScope <- getState >>= return . Scope.expectScopeStruct . snd . ParserState.popScope
closingBrace <- choice return $ Struct (StructScope.structName structScope) (StructScope.variables structScope)
[ UbcLanguage.symbol "}" >>= return . Right
, getPosition >>= return . Left . StructError.MissingBraceError . Right
]
return $ Right $ Struct "" []
structMember :: Monad m => ParsecT String ParserState m () structMember :: Monad m => ParsecT String ParserState m ()
structMember = choice [ structVariableOrFunction ] structMember = choice [ structVariableOrFunction ]
structVariableOrFunction :: Monad m => ParsecT String ParserState m ()
structVariableOrFunction = do structVariableOrFunction = do
(typeName, identifier) <- try $ do
typeName <- UbcLanguage.identifier
objectIdentifier <- UbcLanguage.identifier
return $ (typeName, objectIdentifier)
choice
[ lookAhead (char ';') *> parseVariable typeName identifier
] -- TODO: Functions on structs
parseVariable variableType variableName = do
_ <- UbcLanguage.semicolon
-- TODO: Validate type
(_, structScope) <- getState >>= return . (second Scope.expectScopeStruct) . ParserState.popScope
if (== Nothing) . Map.lookup variableName . StructScope.variables $ structScope
then do
-- variable is not yet defined on the struct
let structScope' = StructScope.modifyVariables (Map.insert variableName (StructVariable variableName variableType)) $ structScope
modifyState (ParserState.pushScope $ ScopeStruct structScope')
else do
unexpected $ "name: \"" ++ variableName ++ "\", this name is already defined"

View file

@ -1,11 +1,19 @@
module Data.String.Ubc.Parse.StructScope module Data.String.Ubc.Parse.StructScope
( StructScope(..) ( StructScope(..)
, modifyVariables
) )
where where
import Data.String.Ubc.Parse.Error.StructError (StructError) import Data.Map (Map)
import Data.String.Ubc.Parse.StructVariable (StructVariable)
data StructScope = StructScope data StructScope = StructScope
{ structName :: Maybe String { structName :: String
, errors :: [StructError] , variables :: Map String StructVariable
} }
modifyVariables :: (Map String StructVariable -> Map String StructVariable) -> StructScope -> StructScope
modifyVariables f scope@StructScope{variables = oldVariables} = scope{variables = newVariables}
where
newVariables = f oldVariables

View file

@ -7,3 +7,5 @@ data StructVariable = StructVariable
{ name :: String { name :: String
, typeName :: String , typeName :: String
} }
deriving (Show, Eq)

View file

@ -17,8 +17,7 @@
# #
# snapshot: ./custom-snapshot.yaml # snapshot: ./custom-snapshot.yaml
# snapshot: https://example.com/snapshots/2024-01-01.yaml # snapshot: https://example.com/snapshots/2024-01-01.yaml
snapshot: snapshot: ghc-9.8.2
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/23/2.yaml
# User packages to be built. # User packages to be built.
# Various formats can be used as shown in the example below. # Various formats can be used as shown in the example below.

View file

@ -1,13 +1,7 @@
# This file was autogenerated by Stack. # This file was autogenerated by Stack.
# You should not edit this file by hand. # You should not edit this file by hand.
# For more information, please see the documentation at: # For more information, please see the documentation at:
# https://docs.haskellstack.org/en/stable/lock_files # https://docs.haskellstack.org/en/stable/topics/lock_files
packages: [] packages: []
snapshots: snapshots: []
- completed:
sha256: 90719ee9e630cf0535cc349cb35e007cec11db9462d598be78cf8ecbabd12c6c
size: 679061
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/23/2.yaml
original:
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/23/2.yaml

View file

@ -26,7 +26,6 @@ source-repository head
library library
exposed-modules: exposed-modules:
Data.String.Ubc.Parse Data.String.Ubc.Parse
Data.String.Ubc.Parse.Error.StructError
Data.String.Ubc.Parse.FileScope Data.String.Ubc.Parse.FileScope
Data.String.Ubc.Parse.Language Data.String.Ubc.Parse.Language
Data.String.Ubc.Parse.ParserState Data.String.Ubc.Parse.ParserState
@ -43,6 +42,7 @@ library
ghc-options: -Wall -Wextra -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints ghc-options: -Wall -Wextra -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints
build-depends: build-depends:
base >=4.7 && <5 base >=4.7 && <5
, containers
, parsec , parsec
default-language: Haskell2010 default-language: Haskell2010
@ -57,6 +57,7 @@ executable ubcc-exe
ghc-options: -Wall -Wextra -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N ghc-options: -Wall -Wextra -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N
build-depends: build-depends:
base >=4.7 && <5 base >=4.7 && <5
, containers
, parsec , parsec
, ubcc , ubcc
default-language: Haskell2010 default-language: Haskell2010
@ -73,6 +74,7 @@ test-suite ubcc-test
ghc-options: -Wall -Wextra -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N ghc-options: -Wall -Wextra -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N
build-depends: build-depends:
base >=4.7 && <5 base >=4.7 && <5
, containers
, parsec , parsec
, ubcc , ubcc
default-language: Haskell2010 default-language: Haskell2010