Implement continuation lines of both kinds
This commit is contained in:
parent
f5345f3815
commit
a93439dfc7
|
@ -5,6 +5,7 @@ import Control.Monad
|
|||
import Control.Monad.Error
|
||||
import Control.Monad.State
|
||||
import Data.List
|
||||
import Text.Regex
|
||||
|
||||
import Errors
|
||||
import ParseState
|
||||
|
@ -14,10 +15,6 @@ import Pass
|
|||
-- what it joined into ParseState so that error reporting later on can
|
||||
-- reconstruct the original position.
|
||||
|
||||
-- FIXME this doesn't handle multi-line strings
|
||||
-- FIXME or VALOF processes
|
||||
-- FIXME or continuation lines...
|
||||
|
||||
indentMarker = "__indent"
|
||||
outdentMarker = "__outdent"
|
||||
eolMarker = "__eol"
|
||||
|
@ -69,21 +66,52 @@ removeIndentation filename orig
|
|||
case psIndentLinesOut ps of (l:ls) -> ((l ++ s):ls) })
|
||||
|
||||
-- | Given a line, read the rest of it, then return the complete thing.
|
||||
finishLine :: String -> String -> Bool -> PassM String
|
||||
finishLine left soFar inStr
|
||||
finishLine :: String -> String -> Bool -> String -> PassM String
|
||||
finishLine left soFar inStr afterStr
|
||||
= case (left, inStr) of
|
||||
([], False) -> plainEOL
|
||||
('-':'-':cs, False) -> plainEOL
|
||||
([], True) -> die "end of line in string without continuation"
|
||||
(['*'], True) -> stringEOL
|
||||
('"':cs, iS) -> finishLine cs ('"':soFar) (not iS)
|
||||
('*':'"':cs, True) -> finishLine cs ('"':'*':soFar) True
|
||||
(c:cs, iS) -> finishLine cs (c:soFar) iS
|
||||
('"':cs, iS) -> finishLine cs (afterStr ++ ('"':soFar)) (not iS) ""
|
||||
('*':'"':cs, True) -> finishLine cs ('"':'*':soFar) True afterStr
|
||||
(c:cs, iS) -> finishLine cs (c:soFar) iS afterStr
|
||||
where
|
||||
-- FIXME check if this should have a continuation
|
||||
plainEOL = return $ reverse soFar
|
||||
-- FIXME implement
|
||||
stringEOL = die "string continues"
|
||||
-- | Finish a regular line.
|
||||
plainEOL :: PassM String
|
||||
plainEOL
|
||||
= do let s = reverse soFar
|
||||
if hasContinuation s
|
||||
then do l <- getLine >>= checkJust "no continuation line"
|
||||
finishLine l ('\n':soFar) False ""
|
||||
else return s
|
||||
|
||||
-- | Finish a line where we're in the middle of a string.
|
||||
stringEOL :: PassM String
|
||||
stringEOL
|
||||
= do l <- getLine >>= checkJust "no string continuation line"
|
||||
l' <- contStringStart l
|
||||
-- When we hit the end of the string, add a \n after it to
|
||||
-- make the line numbers match up again.
|
||||
finishLine l' soFar True ('\n':afterStr)
|
||||
|
||||
-- | Does a line have a continuation line following it?
|
||||
hasContinuation :: String -> Bool
|
||||
hasContinuation s
|
||||
= case matchRegex contRE s of
|
||||
Just _ -> True
|
||||
Nothing -> False
|
||||
where
|
||||
-- FIXME This should probably be based on the list of operators and
|
||||
-- reserved words that the parser already has; for now this is the
|
||||
-- regexp that occamdoc uses.
|
||||
contRE = mkRegexWithOpts "(-|~|\\+|-|\\*|/|\\\\|/\\\\|\\\\/|><|=|<>|<|>|>=|<=|,|;|:=|<<|>>|([[:space:]](MINUS|BITNOT|NOT|SIZE|REM|PLUS|MINUS|TIMES|BITAND|BITOR|AND|OR|AFTER|FROM|FOR|IS|RETYPES|RESHAPES)))[[:space:]]*$" False True
|
||||
|
||||
-- | Strip the spaces-then-star beginning off a string continuation line.
|
||||
contStringStart :: String -> PassM String
|
||||
contStringStart (' ':cs) = contStringStart cs
|
||||
contStringStart ('*':cs) = return cs
|
||||
contStringStart _ = die "string continuation line doesn't start with *"
|
||||
|
||||
-- | Get the next *complete* line from the input, resolving continuations.
|
||||
readLine :: PassM (Maybe String)
|
||||
|
@ -91,7 +119,7 @@ removeIndentation filename orig
|
|||
= do line <- getLine
|
||||
case line of
|
||||
Just s ->
|
||||
do r <- finishLine s "" False
|
||||
do r <- finishLine s "" False ""
|
||||
return $ Just r
|
||||
Nothing -> return Nothing
|
||||
|
||||
|
@ -117,13 +145,13 @@ removeIndentation filename orig
|
|||
Nothing -> return ()
|
||||
Just line ->
|
||||
do (newLevel, stripped) <- countIndent line 0
|
||||
addLine level newLevel stripped
|
||||
addLine level newLevel line stripped
|
||||
|
||||
-- | Once a line's been retrieved, add it to the output along with the
|
||||
-- appropriate markers, then go and process the next one.
|
||||
addLine :: Int -> Int -> String -> PassM ()
|
||||
addLine level newLevel line
|
||||
| line == "" =
|
||||
addLine :: Int -> Int -> String -> String -> PassM ()
|
||||
addLine level newLevel line stripped
|
||||
| stripped == "" =
|
||||
do putLine ""
|
||||
nextLine level
|
||||
| newLevel > level =
|
||||
|
|
|
@ -1722,7 +1722,6 @@ mainProcess :: OccParser A.Process
|
|||
mainProcess
|
||||
= do m <- md
|
||||
sMainMarker
|
||||
eol
|
||||
-- Stash the current locals so that we can either restore them
|
||||
-- when we get back to the file we included this one from, or
|
||||
-- pull the TLP name from them at the end.
|
||||
|
@ -1783,7 +1782,8 @@ loadSource file = load file file
|
|||
Nothing ->
|
||||
do progress $ "Loading source file " ++ realName
|
||||
rawSource <- liftIO $ readSource realName
|
||||
source <- removeIndentation realName (rawSource ++ "\n" ++ mainMarker)
|
||||
source' <- removeIndentation realName rawSource
|
||||
let source = source' ++ "\n" ++ mainMarker ++ "\n"
|
||||
debug $ "Preprocessed source:"
|
||||
debug $ numberLines source
|
||||
modify $ (\ps -> ps { psSourceFiles = (file, source) : psSourceFiles ps })
|
||||
|
|
|
@ -25,8 +25,6 @@ Add an option for whether to compile out overflow/bounds checks.
|
|||
|
||||
## Parser
|
||||
|
||||
The indentation parser is way too simplistic.
|
||||
|
||||
Record literals aren't implemented.
|
||||
|
||||
## Passes
|
||||
|
@ -54,9 +52,6 @@ Multidimensional array literals won't work.
|
|||
We could have genSpec generate {} around specs if it's not immediately inside
|
||||
another spec (which'd require some extra boolean arguments to find out).
|
||||
|
||||
genTopLevel should look at what interface the PROC is actually expecting, like
|
||||
occ21 does.
|
||||
|
||||
If the assembler-analysis approach to working out process sizes works, then we
|
||||
can put the sizes in variables in a separate object file and only
|
||||
generate/compile that after we've done the main one.
|
||||
|
|
Loading…
Reference in New Issue
Block a user