diff --git a/TODO.md b/TODO.md index cf19f54..656df2a 100644 --- a/TODO.md +++ b/TODO.md @@ -29,16 +29,35 @@ with `pEolAndAdvanceToNextNonWs` - [x] Check inline sequencing of whitespace parsers in do blocks. Terminating instances of `pWs` should be preceeded by `<*` + - [ ] Verify no backtracking needed when sequencing `many` parsers. + Basically, we want to make sure that the argument of the `many` + parser doesn't conflict(exhibit a partial early match) with + the argument of the parser after the argument of the `many` parser. # Parser Development - [x] Sync - [ ] Process + - [x] Finish `pCell` with `pCellEndStmt` - [ ] Rewrite `pWireStmt` and `pMemoryStmt` using do-notation... + - [x] Remove all instances of `_ <-` - [ ] Module + - [ ] Remove weird GHC imports + - [ ] Consider the very weird case where the process body has nothing, + thus, `pEolAndAdvanceToNextNonWs` may never get invoked in any of + the sub-parsers encapsulated in `pProcessBody`. Do we need to + advance whitespaces so we can hit ``? + - [ ] What are the implications for other parsers? + + I think that in this case we're OK as `` necessarily + precedes `` and `` terminates in an EOL + parser that advances to the next non-whitespace. + + I still need to verify how other parsers behave. For example, what + happens if we have a cell with no `` # Parser Verification - [ ] I think only EOL terminated parsers should be responsible - for pre-winding the Parsec scanner to the next non-space... + for advancing the Parsec scanner to the next non-space... - [ ] lift grammar into prover and show that all EOL terminated parsers are either followed by EOF or a keyword such "module", "autoidx", etc diff --git a/src/RTLILParser/AST.hs b/src/RTLILParser/AST.hs index 5207597..8a6d3a7 100644 --- a/src/RTLILParser/AST.hs +++ b/src/RTLILParser/AST.hs @@ -139,7 +139,7 @@ data Process = Process ProcStmt [AttrStmt] ProcessBody data ProcStmt = ProcStmt Id deriving (Show) data ProcessBody = ProcessBody [AssignStmt] - Switch + (Maybe Switch) [AssignStmt] [Sync] deriving (Show) diff --git a/src/RTLILParser/Parser.hs b/src/RTLILParser/Parser.hs index 77ccbf5..9a1e318 100644 --- a/src/RTLILParser/Parser.hs +++ b/src/RTLILParser/Parser.hs @@ -37,7 +37,8 @@ import RTLILParser.AST ( CellBodyStmt(..), -- Processes - DestSigSpec(..), SrcSigSpec(..), AssignStmt(..), + Process(..), ProcStmt(..), ProcessBody(..), AssignStmt(..), + DestSigSpec(..), SrcSigSpec(..), -- Switches Switch(..), SwitchStmt(..), Case(..), CaseStmt(..), Compare(..), @@ -55,8 +56,6 @@ import RTLILParser.Primitives( ,pEscapedChar ,pEolAndAdvanceToNextNonWs ) -import Text.Parsec.Token (GenLanguageDef(caseSensitive)) -import GHC.IO.Handle.Types (Handle__(Handle__)) -- taken from: https://yosyshq.readthedocs.io/projects/yosys/en/0.47/appendix/rtlil_text.html -- parsers below are split int sections from the above link @@ -76,7 +75,7 @@ pAutogenId = AutogenId <$> (char '$' *> many1 pNonWs) pValue :: Parser Value pValue = do width <- many1 pDecimalDigit - _ <- char '\'' + char '\'' value <- many pBinaryDigit return $ Value (read width) (binaryStringToInt value) @@ -110,13 +109,13 @@ pString = -- Autoindex statements pAutoIdxStmt :: Parser AutoIdxStmt -pAutoIdxStmt = AutoIdxStmt - <$> (string "autoidx" *> pWs *> +pAutoIdxStmt = AutoIdxStmt + <$> (string "autoidx" *> pWs *> pInteger <* pEolAndAdvanceToNextNonWs) -- Module pModuleStmt :: Parser Id -pModuleStmt = string "module" *> pWs *> pId <* +pModuleStmt = string "module" *> pWs *> pId <* pEolAndAdvanceToNextNonWs pParamStmt :: Parser ParamStmt @@ -153,9 +152,9 @@ pSigSpec = do pSigSpecConcat :: Parser SigSpec pSigSpecConcat = do - _ <- char '{' <* pWs + char '{' <* pWs sigspecs <- pSigSpec `sepBy` pWs - _ <- pWs <* char '}' + pWs <* char '}' return $ SigSpecConcat sigspecs applySlices :: SigSpec -> Parser SigSpec @@ -186,14 +185,11 @@ pWire = do return $ Wire wireStmt attrs pWireStmt :: Parser WireStmt -pWireStmt = - WireStmt - <$ string "wire" - <* pWs - <*> (WireId <$> pId) - <* pWs - <*> many pWireOption - <* pEolAndAdvanceToNextNonWs +pWireStmt = do + string "wire" <* pWs + options <- many pWireOption <* pWs + wireId <- WireId <$> pId <* pEolAndAdvanceToNextNonWs + return $ WireStmt wireId options pWireId :: Parser WireId pWireId = WireId <$> pId @@ -216,14 +212,12 @@ pMemory = do return $ Memory memoryStmt attrs pMemoryStmt :: Parser MemoryStmt -pMemoryStmt = - MemoryStmt - <$ string "memory" - <* pWs - <*> (MemoryID <$> pId) - <* pWs - <*> many pMemoryOption - <* pEolAndAdvanceToNextNonWs +pMemoryStmt = do + (string "memory" <* pWs) + options <- (many pMemoryOption <* pWs) + memoryId <- MemoryID <$> pId + pEolAndAdvanceToNextNonWs + return $ MemoryStmt memoryId options pMemoryOption :: Parser MemoryOption pMemoryOption = @@ -236,17 +230,17 @@ pCell :: Parser Cell pCell = do attrStmts <- many pAttrStmt cellStmt <- pCellStmt - cellBodyStmts <- many pCellBodyStmt + cellBodyStmts <- many pCellBodyStmt <* pCellEndStmt return $ Cell cellStmt attrStmts cellBodyStmts pCellStmt :: Parser CellStmt pCellStmt = do - _ <- string "cell" - _ <- pWs + string "cell" + pWs cellType <- CellType <$> pId - _ <- pWs + pWs cellId <- CellId <$> pId - _ <- pEolAndAdvanceToNextNonWs + pEolAndAdvanceToNextNonWs return $ CellStmt cellId cellType pCellBodyStmt :: Parser CellBodyStmt @@ -259,7 +253,7 @@ pParameterSign = pCellBodyParameter :: Parser CellBodyStmt pCellBodyParameter = do - _ <- string "parameter" <* pWs + string "parameter" <* pWs sign <- optionMaybe pParameterSign <* pMaybeWs id <- pId const <- pConstant <* pEolAndAdvanceToNextNonWs @@ -267,13 +261,41 @@ pCellBodyParameter = do pCellBodyConnect :: Parser CellBodyStmt pCellBodyConnect = do - _ <- string "connect" <* pWs + string "connect" <* pWs id <- pId <* pWs sigSpec <- pSigSpec <* pEolAndAdvanceToNextNonWs return $ CellConnect id sigSpec +pCellEndStmt :: Parser () +pCellEndStmt = void (string "end" <* pEolAndAdvanceToNextNonWs) + -- Processes --- pProcessBody :: +pProcess :: Parser Process +pProcess = do + attrs <- many pAttrStmt + procStmt <- pProcStmt + processBody <- pProcessBody + pProcEndStmt + return $ Process procStmt attrs processBody + +pProcStmt :: Parser ProcStmt +pProcStmt = ProcStmt + <$> (string "process" *> pWs *> pId) + <* pEolAndAdvanceToNextNonWs + +pProcessBody :: Parser ProcessBody +pProcessBody = do + -- Since the pAssignStmt parser begins with "assign" and the pSwitch + -- parser technically begins with "attribute", these both starting + -- with the character 'a', we need to be able to rewind failed + -- attempts for `pAssignStmt` and `pSwitch` parsers as the first + -- character being an 'a' would have been consumed. + assignStmtsBefore <- many $ try pAssignStmt + switch <- optionMaybe $ try pSwitch + assignStmtsAfter <- many pAssignStmt + syncs <- many pSync + return $ ProcessBody assignStmtsBefore switch assignStmtsAfter syncs + pAssignStmt :: Parser AssignStmt pAssignStmt = AssignStmt <$> (string "assign" *> pWs *> pDestSigSpec) @@ -297,7 +319,7 @@ pSwitch = Switch pSwitchStmt :: Parser SwitchStmt pSwitchStmt = do attrs <- many pAttrStmt - _ <- string "switch" <* pWs + string "switch" <* pWs sigspec <- pSigSpec <* pEolAndAdvanceToNextNonWs return $ SwitchStmt sigspec attrs @@ -310,8 +332,8 @@ pCase = Case pCaseStmt :: Parser CaseStmt pCaseStmt = CaseStmt <$> ( - string "case" *> pWs - *> optionMaybe pCompare + string "case" *> pWs + *> optionMaybe pCompare <* pEolAndAdvanceToNextNonWs) pCompare :: Parser Compare @@ -337,7 +359,7 @@ pSync = Sync pSyncStmt :: Parser SyncStmt pSyncStmt = pKeywordSync *> - pSigSpecPredicatedSyncStmt <|> + pSigSpecPredicatedSyncStmt <|> pNonSigSpecPredicatedSyncStmt where pKeywordSync = string "sync" *> pWs @@ -348,7 +370,7 @@ pSigSpecPredicatedSyncStmt = do return $ SigSpecPredicated sigSpec syncType pNonSigSpecPredicatedSyncStmt :: Parser SyncStmt -pNonSigSpecPredicatedSyncStmt = +pNonSigSpecPredicatedSyncStmt = keyword <* pEolAndAdvanceToNextNonWs where keyword = (Global <$ string "global" ) <|>