Big parser rework: remove all the extraneous "try" calls in favour of more specific commits

This commit is contained in:
Adam Sampson 2007-04-25 01:33:30 +00:00
parent 90643cb56b
commit a1f045260b
3 changed files with 403 additions and 209 deletions

View File

@ -208,7 +208,7 @@ genLiteral l = missing $ "genLiteral " ++ show l
genLiteralRepr :: A.LiteralRepr -> CGen ()
genLiteralRepr (A.RealLiteral m s) = tell [s]
genLiteralRepr (A.IntLiteral m s) = tell [s]
genLiteralRepr (A.HexLiteral m s) = case s of ('#':rest) -> tell ["0x", rest]
genLiteralRepr (A.HexLiteral m s) = tell ["0x", s]
genLiteralRepr (A.ByteLiteral m s) = tell ["'", convStringLiteral s, "'"]
genLiteralRepr (A.StringLiteral m s) = tell ["\"", convStringLiteral s, "\""]
genLiteralRepr (A.ArrayLiteral m es)

View File

@ -256,21 +256,65 @@ md
metaColumn = sourceColumn pos
}
tryVX :: OccParser a -> OccParser b -> OccParser a
tryVX p q = try (do { v <- p; q; return v })
--{{{ try*
-- These functions let you try a sequence of productions and only retrieve the
-- results from some of them. In the function name, X represents a value
-- that'll be thrown away, and V one that'll be kept; you get back a tuple of
-- the values you wanted.
--
-- There isn't anything particularly unusual going on here; it's just a more
-- succinct way of writing a try (do { ... }) expression.
tryXX :: OccParser a -> OccParser b -> OccParser ()
tryXX a b = try (do { a; b; return () })
tryXV :: OccParser a -> OccParser b -> OccParser b
tryXV p q = try (do { p; q })
tryXV a b = try (do { a; b })
tryXVV :: OccParser a -> OccParser b -> OccParser c -> OccParser (b, c)
tryXVV a b c = try (do { a; bv <- b; cv <- c; return (bv, cv) })
tryVX :: OccParser a -> OccParser b -> OccParser a
tryVX a b = try (do { av <- a; b; return av })
tryVV :: OccParser a -> OccParser b -> OccParser (a, b)
tryVV a b = try (do { av <- a; bv <- b; return (av, bv) })
tryXXV :: OccParser a -> OccParser b -> OccParser c -> OccParser c
tryXXV a b c = try (do { a; b; cv <- c; return cv })
tryXVX :: OccParser a -> OccParser b -> OccParser c -> OccParser b
tryXVX a b c = try (do { a; bv <- b; c; return bv })
tryXVV :: OccParser a -> OccParser b -> OccParser c -> OccParser (b, c)
tryXVV a b c = try (do { a; bv <- b; cv <- c; return (bv, cv) })
tryVXX :: OccParser a -> OccParser b -> OccParser c -> OccParser a
tryVXX a b c = try (do { av <- a; b; c; return av })
tryVXV :: OccParser a -> OccParser b -> OccParser c -> OccParser (a, c)
tryVXV a b c = try (do { av <- a; b; cv <- c; return (av, cv) })
tryVVX :: OccParser a -> OccParser b -> OccParser c -> OccParser (a, b)
tryVVX a b c = try (do { av <- a; bv <- b; c; return (av, bv) })
tryXVXV :: OccParser a -> OccParser b -> OccParser c -> OccParser d -> OccParser (b, d)
tryXVXV a b c d = try (do { a; bv <- b; c; dv <- d; return (bv, dv) })
tryXVVX :: OccParser a -> OccParser b -> OccParser c -> OccParser d -> OccParser (b, c)
tryXVVX a b c d = try (do { a; bv <- b; cv <- c; d; return (bv, cv) })
tryVXVX :: OccParser a -> OccParser b -> OccParser c -> OccParser d -> OccParser (a, c)
tryVXVX a b c d = try (do { av <- a; b; cv <- c; d; return (av, cv) })
tryVVXX :: OccParser a -> OccParser b -> OccParser c -> OccParser d -> OccParser (a, b)
tryVVXX a b c d = try (do { av <- a; bv <- b; c; d; return (av, bv) })
tryVVXV :: OccParser a -> OccParser b -> OccParser c -> OccParser d -> OccParser (a, b, d)
tryVVXV a b c d = try (do { av <- a; bv <- b; c; dv <- d; return (av, bv, dv) })
tryVXVXX :: OccParser a -> OccParser b -> OccParser c -> OccParser d -> OccParser e -> OccParser (a, c)
tryVXVXX a b c d e = try (do { av <- a; b; cv <- c; d; e; return (av, cv) })
--}}}
--{{{ subscripts
maybeSubscripted :: String -> OccParser a -> (Meta -> A.Subscript -> a -> a) -> (a -> OccParser A.Type) -> OccParser a
maybeSubscripted prodName inner subscripter typer
= do m <- md
@ -330,6 +374,7 @@ maybeSliced inner subscripter typer
where
fromOrFor :: OccParser String
fromOrFor = (sFROM >> return "FROM") <|> (sFOR >> return "FOR")
--}}}
handleSpecs :: OccParser [A.Specification] -> OccParser a -> (Meta -> A.Specification -> a -> a) -> OccParser a
handleSpecs specs inner specMarker
@ -510,6 +555,11 @@ newFieldName = anyName A.FieldName
newTagName = anyName A.TagName
--}}}
--{{{ types
arrayType :: OccParser A.Type -> OccParser A.Type
arrayType element
= do (s, t) <- tryXVXV sLeft constIntExpr sRight element
return $ makeArrayType (A.Dimension s) t
dataType :: OccParser A.Type
dataType
= do { sBOOL; return A.Bool }
@ -520,65 +570,68 @@ dataType
<|> do { sINT64; return A.Int64 }
<|> do { sREAL32; return A.Real32 }
<|> do { sREAL64; return A.Real64 }
<|> try (do { sLeft; s <- constIntExpr; sRight; t <- dataType; return $ makeArrayType (A.Dimension s) t })
<|> do { n <- dataTypeName; return $ A.UserDataType n }
<|> arrayType dataType
<|> do { n <- try dataTypeName; return $ A.UserDataType n }
<?> "dataType"
-- FIXME should probably make CHAN INT work, since that'd be trivial...
channelType :: OccParser A.Type
channelType
= do { sCHAN; sOF; p <- protocol; return $ A.Chan p }
<|> try (do { sLeft; s <- constIntExpr; sRight; t <- channelType; return $ makeArrayType (A.Dimension s) t })
<|> arrayType channelType
<?> "channelType"
timerType :: OccParser A.Type
timerType
= do { sTIMER; return $ A.Timer }
<|> try (do { sLeft; s <- constIntExpr; sRight; t <- timerType; return $ makeArrayType (A.Dimension s) t })
<|> arrayType timerType
<?> "timerType"
portType :: OccParser A.Type
portType
= do { sPORT; sOF; p <- dataType; return $ A.Port p }
<|> do { m <- md; try sLeft; s <- try constIntExpr; try sRight; t <- portType; return $ makeArrayType (A.Dimension s) t }
<|> arrayType portType
<?> "portType"
--}}}
--{{{ literals
literal :: OccParser A.Literal
literal
= try (do { m <- md; v <- real; sLeftR; t <- dataType; sRightR; return $ A.Literal m t v })
<|> try (do { m <- md; v <- integer; sLeftR; t <- dataType; sRightR; return $ A.Literal m t v })
<|> try (do { m <- md; v <- byte; sLeftR; t <- dataType; sRightR; return $ A.Literal m t v })
<|> try (do { m <- md; r <- real; return $ A.Literal m A.Real32 r })
<|> try (do { m <- md; r <- integer; return $ A.Literal m A.Int r })
<|> try (do { m <- md; r <- byte; return $ A.Literal m A.Byte r })
= do m <- md
(defT, lr) <- untypedLiteral
do { try sLeftR; t <- dataType; sRightR; return $ A.Literal m t lr }
<|> (return $ A.Literal m defT lr)
<?> "literal"
untypedLiteral :: OccParser (A.Type, A.LiteralRepr)
untypedLiteral
= do { r <- real; return (A.Real32, r) }
<|> do { r <- integer; return (A.Int, r) }
<|> do { r <- byte; return (A.Byte, r) }
real :: OccParser A.LiteralRepr
real
= try (do m <- md
l <- digits
char '.'
r <- digits
char 'e'
e <- lexeme occamExponent
return $ A.RealLiteral m (l ++ "." ++ r ++ "e" ++ e))
= do m <- md
(l, r) <- tryVXVX digits (char '.') digits (char 'E')
e <- lexeme occamExponent
return $ A.RealLiteral m (l ++ "." ++ r ++ "E" ++ e)
<|> do m <- md
l <- digits
char '.'
l <- tryVX digits (char '.')
r <- lexeme digits
return $ A.RealLiteral m (l ++ "." ++ r)
<?> "real"
occamExponent :: OccParser String
occamExponent
= try (do { c <- oneOf "+-"; d <- digits; return $ c : d })
= do c <- oneOf "+-"
d <- digits
return $ c : d
<?> "exponent"
integer :: OccParser A.LiteralRepr
integer
= try (do { m <- md; d <- lexeme digits; return $ A.IntLiteral m d })
<|> do { m <- md; sHash; d <- many1 hexDigit; return $ A.HexLiteral m d }
= do m <- md
do { d <- lexeme digits; return $ A.IntLiteral m d }
<|> do { sHash; d <- many1 hexDigit; return $ A.HexLiteral m d }
<?> "integer"
digits :: OccParser String
@ -588,7 +641,11 @@ digits
byte :: OccParser A.LiteralRepr
byte
= do { m <- md; char '\''; s <- character; sApos; return $ A.ByteLiteral m s }
= do m <- md
char '\''
s <- character
sApos
return $ A.ByteLiteral m s
<?> "byte"
-- i.e. array literal
@ -599,8 +656,10 @@ table
table' :: OccParser A.Literal
table'
-- FIXME Check dimensions match
= try (do { m <- md; (s, dim) <- stringLiteral; sLeftR; t <- dataType; sRightR; return $ A.Literal m t s })
<|> try (do { m <- md; (s, dim) <- stringLiteral; return $ A.Literal m (A.Array [dim] A.Byte) s })
= do m <- md
(s, dim) <- stringLiteral
do { sLeftR; t <- dataType; sRightR; return $ A.Literal m t s }
<|> (return $ A.Literal m (A.Array [dim] A.Byte) s)
<|> do m <- md
es <- tryXVX sLeft (sepBy1 expression sComma) sRight
ets <- mapM typeOfExpression es
@ -611,19 +670,23 @@ table'
stringLiteral :: OccParser (A.LiteralRepr, A.Dimension)
stringLiteral
= do { m <- md; char '"'; cs <- manyTill character sQuote; return $ (A.StringLiteral m $ concat cs, A.Dimension $ makeConstant m $ length cs) }
= do m <- md
char '"'
cs <- manyTill character sQuote
return (A.StringLiteral m $ concat cs, A.Dimension $ makeConstant m $ length cs)
<?> "stringLiteral"
character :: OccParser String
character
= try (do { char '*' ;
do char '#'
a <- hexDigit
b <- hexDigit
return $ ['*', '#', a, b]
-- FIXME: Handle *\n, which is just a line continuation?
<|> do { c <- anyChar; return ['*', c] } })
<|> do { c <- anyChar; return [c] }
= do char '*'
(do char '#'
a <- hexDigit
b <- hexDigit
return $ ['*', '#', a, b])
-- FIXME: Handle *\n, which is just a line continuation?
<|> do { c <- anyChar; return ['*', c] }
<|> do c <- anyChar
return [c]
<?> "character"
--}}}
--{{{ expressions
@ -645,7 +708,7 @@ functionNameMulti :: OccParser A.Name
expressionList :: OccParser A.ExpressionList
expressionList
= try (do { m <- md; n <- functionNameMulti; sLeftR; as <- sepBy expression sComma; sRightR; return $ A.FunctionCallList m n as })
= do { m <- md; n <- try functionNameMulti; sLeftR; as <- sepBy expression sComma; sRightR; return $ A.FunctionCallList m n as }
<|> do { m <- md; es <- sepBy1 expression sComma; return $ A.ExpressionList m es }
-- XXX: Value processes are not supported (because nobody uses them and they're hard to parse)
<?> "expressionList"
@ -658,8 +721,8 @@ expression
<|> sizeExpr
<|> do { m <- md; sTRUE; return $ A.True m }
<|> do { m <- md; sFALSE; return $ A.False m }
<|> try (do { m <- md; l <- operand; o <- dyadicOperator; r <- operand; return $ A.Dyadic m o l r })
<|> try conversion
<|> do { m <- md; (l, o) <- tryVV operand dyadicOperator; r <- operand; return $ A.Dyadic m o l r }
<|> conversion
<|> operand
<?> "expression"
@ -667,9 +730,9 @@ sizeExpr :: OccParser A.Expression
sizeExpr
= do m <- md
sSIZE
(try (do { t <- dataType; return $ A.SizeType m t })
<|> do { v <- operand; return $ A.SizeExpr m v }
<|> do { v <- channel <|> timer <|> port; return $ A.SizeVariable m v })
do { t <- dataType; return $ A.SizeType m t }
<|> do { v <- operand; return $ A.SizeExpr m v }
<|> do { v <- channel <|> timer <|> port; return $ A.SizeVariable m v }
<?> "sizeExpr"
exprOfType :: A.Type -> OccParser A.Expression
@ -726,10 +789,10 @@ dyadicOperator
conversion :: OccParser A.Expression
conversion
= try (do m <- md
t <- dataType
(c, o) <- conversionMode
return $ A.Conversion m c t o)
= do m <- md
t <- dataType
(c, o) <- conversionMode
return $ A.Conversion m c t o
<?> "conversion"
conversionMode :: OccParser (A.ConversionMode, A.Expression)
@ -747,7 +810,7 @@ operand
operand' :: OccParser A.Expression
operand'
= try (do { m <- md; l <- table; return $ A.ExprLiteral m l })
= do { m <- md; l <- table; return $ A.ExprLiteral m l }
<|> operandNotTable'
<?> "operand'"
@ -757,14 +820,17 @@ operandNotTable
operandNotTable' :: OccParser A.Expression
operandNotTable'
= try (do { m <- md; v <- variable; return $ A.ExprVariable m v })
<|> try (do { m <- md; l <- literal; return $ A.ExprLiteral m l })
<|> try (do { sLeftR; e <- expression; sRightR; return e })
= do { m <- md; v <- variable; return $ A.ExprVariable m v }
<|> do { m <- md; l <- literal; return $ A.ExprLiteral m l }
<|> do { sLeftR; e <- expression; sRightR; return e }
-- XXX value process
<|> try (do { m <- md; n <- functionNameSingle; sLeftR; as <- sepBy expression sComma; sRightR; return $ A.FunctionCall m n as })
<|> try (do { m <- md; sBYTESIN; sLeftR; o <- operand; sRightR; return $ A.BytesInExpr m o })
<|> try (do { m <- md; sBYTESIN; sLeftR; t <- dataType; sRightR; return $ A.BytesInType m t })
<|> try (do { m <- md; sOFFSETOF; sLeftR; t <- dataType; sComma; f <- fieldName; sRightR; return $ A.OffsetOf m t f })
<|> do { m <- md; n <- try functionNameSingle; sLeftR; as <- sepBy expression sComma; sRightR; return $ A.FunctionCall m n as }
<|> do m <- md
sBYTESIN
sLeftR
do { o <- operand; sRightR; return $ A.BytesInExpr m o }
<|> do { t <- dataType; sRightR; return $ A.BytesInType m t }
<|> do { m <- md; sOFFSETOF; sLeftR; t <- dataType; sComma; f <- fieldName; sRightR; return $ A.OffsetOf m t f }
<?> "operandNotTable'"
--}}}
--{{{ variables, channels, timers, ports
@ -774,8 +840,8 @@ variable
variable' :: OccParser A.Variable
variable'
= try (do { m <- md; n <- variableName; return $ A.Variable m n })
<|> try (maybeSliced variable A.SubscriptedVariable typeOfVariable)
= do { m <- md; n <- try variableName; return $ A.Variable m n }
<|> maybeSliced variable A.SubscriptedVariable typeOfVariable
<?> "variable'"
channel :: OccParser A.Variable
@ -785,8 +851,8 @@ channel
channel' :: OccParser A.Variable
channel'
= try (do { m <- md; n <- channelName; return $ A.Variable m n })
<|> try (maybeSliced channel A.SubscriptedVariable typeOfVariable)
= do { m <- md; n <- try channelName; return $ A.Variable m n }
<|> maybeSliced channel A.SubscriptedVariable typeOfVariable
<?> "channel'"
timer :: OccParser A.Variable
@ -796,8 +862,8 @@ timer
timer' :: OccParser A.Variable
timer'
= try (do { m <- md; n <- timerName; return $ A.Variable m n })
<|> try (maybeSliced timer A.SubscriptedVariable typeOfVariable)
= do { m <- md; n <- try timerName; return $ A.Variable m n }
<|> maybeSliced timer A.SubscriptedVariable typeOfVariable
<?> "timer'"
port :: OccParser A.Variable
@ -807,20 +873,20 @@ port
port' :: OccParser A.Variable
port'
= try (do { m <- md; n <- portName; return $ A.Variable m n })
<|> try (maybeSliced port A.SubscriptedVariable typeOfVariable)
= do { m <- md; n <- try portName; return $ A.Variable m n }
<|> maybeSliced port A.SubscriptedVariable typeOfVariable
<?> "port'"
--}}}
--{{{ protocols
protocol :: OccParser A.Type
protocol
= try (do { n <- protocolName ; return $ A.UserProtocol n })
= do { n <- try protocolName ; return $ A.UserProtocol n }
<|> simpleProtocol
<?> "protocol"
simpleProtocol :: OccParser A.Type
simpleProtocol
= try (do { l <- dataType; sColons; sLeft; sRight; r <- dataType; return $ A.Counted l r })
= do { l <- tryVX dataType sColons; sLeft; sRight; r <- dataType; return $ A.Counted l r }
<|> dataType
<|> do { sANY; return $ A.Any }
<?> "simpleProtocol"
@ -832,8 +898,8 @@ sequentialProtocol
taggedProtocol :: OccParser (A.Name, [A.Type])
taggedProtocol
= try (do { t <- newTagName; eol; return (t, []) })
<|> try (do { t <- newTagName; sSemi; sp <- sequentialProtocol; eol; return (t, sp) })
= do { t <- tryVX newTagName eol; return (t, []) }
<|> do { t <- newTagName; sSemi; sp <- sequentialProtocol; eol; return (t, sp) }
<?> "taggedProtocol"
--}}}
--{{{ replicators
@ -855,33 +921,34 @@ allocation
specification :: OccParser [A.Specification]
specification
= try (do { m <- md; (ns, d) <- declaration; return [A.Specification m n d | n <- ns] })
<|> try (do { a <- abbreviation; return [a] })
= do { m <- md; (ns, d) <- declaration; return [A.Specification m n d | n <- ns] }
<|> do { a <- abbreviation; return [a] }
<|> do { d <- definition; return [d] }
<?> "specification"
declaration :: OccParser ([A.Name], A.SpecType)
declaration
= do { m <- md; d <- dataType; ns <- sepBy1 newVariableName sComma; sColon; eol; return (ns, A.Declaration m d) }
<|> do { m <- md; d <- channelType; ns <- sepBy1 newChannelName sComma; sColon; eol; return (ns, A.Declaration m d) }
<|> do { m <- md; d <- timerType; ns <- sepBy1 newTimerName sComma; sColon; eol; return (ns, A.Declaration m d) }
<|> do { m <- md; d <- portType; ns <- sepBy1 newPortName sComma; sColon; eol; return (ns, A.Declaration m d) }
= declOf dataType newVariableName
<|> declOf channelType newChannelName
<|> declOf timerType newTimerName
<|> declOf portType newPortName
<?> "declaration"
declOf :: OccParser A.Type -> OccParser A.Name -> OccParser ([A.Name], A.SpecType)
declOf spec newName
= do m <- md
(d, ns) <- tryVVX spec (sepBy1 newName sComma) sColon
eol
return (ns, A.Declaration m d)
abbreviation :: OccParser A.Specification
abbreviation
= do m <- md
(do { (n, v) <- tryVXV newVariableName sIS variable; sColon; eol; t <- typeOfVariable v; return $ A.Specification m n $ A.Is m A.Abbrev t v }
<|> do { (s, n, v) <- try (do { s <- specifier; n <- newVariableName; sIS; v <- variable; return (s, n, v) }); sColon; eol; t <- typeOfVariable v; matchType s t; return $ A.Specification m n $ A.Is m A.Abbrev s v }
<|> valIsAbbrev
<|> try (do { n <- newChannelName; sIS; c <- channel; sColon; eol; t <- typeOfVariable c; return $ A.Specification m n $ A.Is m A.Abbrev t c })
<|> try (do { n <- newTimerName; sIS; c <- timer; sColon; eol; t <- typeOfVariable c; return $ A.Specification m n $ A.Is m A.Abbrev t c })
<|> try (do { n <- newPortName; sIS; c <- port; sColon; eol; t <- typeOfVariable c; return $ A.Specification m n $ A.Is m A.Abbrev t c })
<|> try (do { s <- specifier; n <- newChannelName; sIS; c <- channel; sColon; eol; t <- typeOfVariable c; matchType s t; return $ A.Specification m n $ A.Is m A.Abbrev s c })
<|> try (do { s <- specifier; n <- newTimerName; sIS; c <- timer; sColon; eol; t <- typeOfVariable c; matchType s t; return $ A.Specification m n $ A.Is m A.Abbrev s c })
<|> try (do { s <- specifier; n <- newPortName; sIS; c <- port; sColon; eol; t <- typeOfVariable c; matchType s t; return $ A.Specification m n $ A.Is m A.Abbrev s c })
<|> try (do { n <- newChannelName; sIS; sLeft; cs <- sepBy1 channel sComma; sRight; sColon; eol; ts <- mapM typeOfVariable cs; t <- listType m ts; return $ A.Specification m n $ A.IsChannelArray m t cs })
<|> try (do { s <- specifier; n <- newChannelName; sIS; sLeft; cs <- sepBy1 channel sComma; sRight; sColon; eol; ts <- mapM typeOfVariable cs; t <- listType m ts; matchType s t; return $ A.Specification m n $ A.IsChannelArray m s cs }))
= valIsAbbrev
<|> chanArrayAbbrev
<|> isAbbrev newVariableName variable
<|> isAbbrev newChannelName channel
<|> isAbbrev newTimerName timer
<|> isAbbrev newPortName port
<?> "abbreviation"
valIsAbbrev :: OccParser A.Specification
@ -893,37 +960,112 @@ valIsAbbrev
return $ A.Specification m n $ A.IsExpr m A.ValAbbrev t e
<?> "VAL IS abbreviation"
isAbbrev :: OccParser A.Name -> OccParser A.Variable -> OccParser A.Specification
isAbbrev newName oldVar
= do m <- md
(n, v) <- tryVXV newName sIS oldVar
sColon
eol
t <- typeOfVariable v
return $ A.Specification m n $ A.Is m A.Abbrev t v
<|> do m <- md
(s, n, v) <- tryVVXV specifier newName sIS oldVar
sColon
eol
t <- typeOfVariable v
matchType s t
return $ A.Specification m n $ A.Is m A.Abbrev s v
<?> "IS abbreviation"
chanArrayAbbrev :: OccParser A.Specification
chanArrayAbbrev
= do m <- md
n <- tryVXX newChannelName sIS sLeft
cs <- sepBy1 channel sComma
sRight
sColon
eol
ts <- mapM typeOfVariable cs
t <- listType m ts
return $ A.Specification m n $ A.IsChannelArray m t cs
<|> do m <- md
(s, n) <- tryVVXX specifier newChannelName sIS sLeft
cs <- sepBy1 channel sComma
sRight
sColon
eol
ts <- mapM typeOfVariable cs
t <- listType m ts
matchType s t
return $ A.Specification m n $ A.IsChannelArray m s cs
<?> "channel array abbreviation"
definition :: OccParser A.Specification
definition
= do { m <- md; sDATA; sTYPE; n <- newDataTypeName ;
do {sIS; t <- dataType; sColon; eol; return $ A.Specification m n (A.DataType m t) }
<|> do { eol; indent; rec <- structuredType; outdent; sColon; eol; return $ A.Specification m n rec } }
<|> do { m <- md; sPROTOCOL; n <- newProtocolName ;
do { sIS; p <- sequentialProtocol; sColon; eol; return $ A.Specification m n $ A.Protocol m p }
<|> do { eol; indent; sCASE; eol; indent; ps <- many1 taggedProtocol; outdent; outdent; sColon; eol; return $ A.Specification m n $ A.ProtocolCase m ps } }
<|> do { m <- md; sPROC; n <- newProcName; fs <- formalList; eol; indent; fs' <- scopeInFormals fs; p <- process; scopeOutFormals fs'; outdent; sColon; eol; return $ A.Specification m n $ A.Proc m fs' p }
<|> try (do { m <- md; rs <- sepBy1 dataType sComma; (n, fs) <- functionHeader ;
do { sIS; fs' <- scopeInFormals fs; el <- expressionList; scopeOutFormals fs'; sColon; eol; return $ A.Specification m n $ A.Function m rs fs' (A.ValOf m (A.Skip m) el) }
<|> do { eol; indent; fs' <- scopeInFormals fs; vp <- valueProcess; scopeOutFormals fs'; outdent; sColon; eol; return $ A.Specification m n $ A.Function m rs fs' vp } })
<|> try (do { m <- md; s <- specifier; n <- newVariableName ;
sRETYPES <|> sRESHAPES; v <- variable; sColon; eol; return $ A.Specification m n $ A.Retypes m A.Abbrev s v })
<|> try (do { m <- md; sVAL; s <- specifier; n <- newVariableName ;
sRETYPES <|> sRESHAPES; e <- expression; sColon; eol; return $ A.Specification m n $ A.RetypesExpr m A.ValAbbrev s e })
= do m <- md
sDATA
sTYPE
n <- newDataTypeName
do { sIS; t <- dataType; sColon; eol; return $ A.Specification m n (A.DataType m t) }
<|> do { eol; indent; rec <- structuredType; outdent; sColon; eol; return $ A.Specification m n rec }
<|> do m <- md
sPROTOCOL
n <- newProtocolName
do { sIS; p <- sequentialProtocol; sColon; eol; return $ A.Specification m n $ A.Protocol m p }
<|> do { eol; indent; sCASE; eol; indent; ps <- many1 taggedProtocol; outdent; outdent; sColon; eol; return $ A.Specification m n $ A.ProtocolCase m ps }
<|> do m <- md
sPROC
n <- newProcName
fs <- formalList
eol
indent
fs' <- scopeInFormals fs
p <- process
scopeOutFormals fs'
outdent
sColon
eol
return $ A.Specification m n $ A.Proc m fs' p
<|> do m <- md
rs <- tryVX (sepBy1 dataType sComma) sFUNCTION
n <- newFunctionName
fs <- formalList
do { sIS; fs' <- scopeInFormals fs; el <- expressionList; scopeOutFormals fs'; sColon; eol; return $ A.Specification m n $ A.Function m rs fs' (A.ValOf m (A.Skip m) el) }
<|> do { eol; indent; fs' <- scopeInFormals fs; vp <- valueProcess; scopeOutFormals fs'; outdent; sColon; eol; return $ A.Specification m n $ A.Function m rs fs' vp }
<|> retypesAbbrev
<?> "definition"
retypesAbbrev :: OccParser A.Specification
retypesAbbrev
= do m <- md
(s, n) <- tryVVX specifier newVariableName (sRETYPES <|> sRESHAPES)
v <- variable
sColon
eol
return $ A.Specification m n $ A.Retypes m A.Abbrev s v
<|> do m <- md
(s, n) <- tryXVVX sVAL specifier newVariableName (sRETYPES <|> sRESHAPES)
e <- expression
sColon
eol
return $ A.Specification m n $ A.RetypesExpr m A.ValAbbrev s e
<?> "RETYPES/RESHAPES abbreviation"
dataSpecifier :: OccParser A.Type
dataSpecifier
= try dataType
<|> try (do { sLeft; sRight; s <- dataSpecifier; return $ makeArrayType A.UnknownDimension s })
= dataType
<|> do s <- tryXXV sLeft sRight dataSpecifier
return $ makeArrayType A.UnknownDimension s
<?> "dataSpecifier"
specifier :: OccParser A.Type
specifier
= try dataType
<|> try channelType
<|> try timerType
<|> try portType
<|> try (do { sLeft; sRight; s <- specifier; return $ makeArrayType A.UnknownDimension s })
= dataType
<|> channelType
<|> timerType
<|> portType
<|> do s <- tryXXV sLeft sRight specifier
return $ makeArrayType A.UnknownDimension s
<?> "specifier"
--{{{ PROCs and FUNCTIONs
@ -938,28 +1080,36 @@ formalList
formalArgSet :: OccParser [A.Formal]
formalArgSet
= try (do (am, t) <- formalVariableType
ns <- sepBy1NE newVariableName sComma
return [A.Formal am t n | n <- ns])
= do (am, t) <- formalVariableType
ns <- sepBy1NE newVariableName sComma
return [A.Formal am t n | n <- ns]
<|> do t <- specifier
ns <- sepBy1NE newChannelName sComma
return [A.Formal A.Abbrev t n | n <- ns]
<?> "formalArgSet"
formalVariableType :: OccParser (A.AbbrevMode, A.Type)
= try (do { sVAL; s <- dataSpecifier; return (A.ValAbbrev, s) })
<|> do { s <- dataSpecifier; return (A.Abbrev, s) }
= do sVAL
s <- dataSpecifier
return (A.ValAbbrev, s)
<|> do s <- dataSpecifier
return (A.Abbrev, s)
<?> "formalVariableType"
functionHeader :: OccParser (A.Name, [A.Formal])
functionHeader
= do { sFUNCTION; n <- newFunctionName; fs <- formalList; return $ (n, fs) }
<?> "functionHeader"
valueProcess :: OccParser A.ValueProcess
valueProcess
= try (do { m <- md; sVALOF; eol; indent; p <- process; sRESULT; el <- expressionList; eol; outdent; return $ A.ValOf m p el })
= do m <- md
sVALOF
eol
indent
p <- process
sRESULT
el <- expressionList
eol
outdent
return $ A.ValOf m p el
<|> handleSpecs specification valueProcess A.ValOfSpec
<?> "value process"
--}}}
--{{{ RECORDs
structuredType :: OccParser A.SpecType
@ -981,7 +1131,11 @@ recordKeyword
structuredTypeField :: OccParser [(A.Name, A.Type)]
structuredTypeField
= do { t <- dataType; fs <- many1 newFieldName; sColon; eol; return [(f, t) | f <- fs] }
= do t <- dataType
fs <- many1 newFieldName
sColon
eol
return [(f, t) | f <- fs]
<?> "structuredTypeField"
--}}}
--}}}
@ -1009,13 +1163,12 @@ process
--{{{ assignment (:=)
assignment :: OccParser A.Process
assignment
= do { m <- md; vs <- tryVX variableList sAssign; es <- expressionList; eol; return $ A.Assign m vs es }
= do m <- md
vs <- tryVX (sepBy1 variable sComma) sAssign
es <- expressionList
eol
return $ A.Assign m vs es
<?> "assignment"
variableList :: OccParser [A.Variable]
variableList
= do { vs <- sepBy1 variable sComma; return $ vs }
<?> "variableList"
--}}}
--{{{ input (?)
inputProcess :: OccParser A.Process
@ -1023,55 +1176,73 @@ inputProcess
= do m <- md
(c, i) <- input
return $ A.Input m c i
<?> "input process"
input :: OccParser (A.Variable, A.InputMode)
input
= channelInput
<|> timerInput
<|> do { m <- md; p <- tryVX port sQuest; v <- variable; eol; return (p, A.InputSimple m [A.InVariable m v]) }
<|> do m <- md
p <- tryVX port sQuest
v <- variable
eol
return (p, A.InputSimple m [A.InVariable m v])
<?> "input"
channelInput :: OccParser (A.Variable, A.InputMode)
= do m <- md
c <- tryVX channel sQuest
(do { tl <- try (do { sCASE; taggedList }); eol; return (c, A.InputCase m (A.OnlyV m (tl (A.Skip m)))) }
= do m <- md
c <- tryVX channel sQuest
do { sCASE; tl <- taggedList; eol; return (c, A.InputCase m (A.OnlyV m (tl (A.Skip m)))) }
<|> do { sAFTER; e <- intExpr; eol; return (c, A.InputAfter m e) }
<|> do { is <- sepBy1 inputItem sSemi; eol; return (c, A.InputSimple m is) })
<|> do { is <- sepBy1 inputItem sSemi; eol; return (c, A.InputSimple m is) }
<?> "channelInput"
timerInput :: OccParser (A.Variable, A.InputMode)
= do m <- md
c <- tryVX timer sQuest
(do { v <- variable; eol; return (c, A.InputSimple m [A.InVariable m v]) }
<|> do { sAFTER; e <- intExpr; eol; return (c, A.InputAfter m e) })
= do m <- md
c <- tryVX timer sQuest
do { v <- variable; eol; return (c, A.InputSimple m [A.InVariable m v]) }
<|> do { sAFTER; e <- intExpr; eol; return (c, A.InputAfter m e) }
<?> "timerInput"
taggedList :: OccParser (A.Process -> A.Variant)
taggedList
= try (do { m <- md; t <- tagName; sSemi; is <- sepBy1 inputItem sSemi; return $ A.Variant m t is })
<|> do { m <- md; t <- tagName; return $ A.Variant m t [] }
= do m <- md
t <- tagName
do { try sSemi; is <- sepBy1 inputItem sSemi; return $ A.Variant m t is }
<|> (return $ A.Variant m t [])
<?> "taggedList"
inputItem :: OccParser A.InputItem
inputItem
= try (do { m <- md; v <- variable; sColons; w <- variable; return $ A.InCounted m v w })
<|> do { m <- md; v <- variable; return $ A.InVariable m v }
= do m <- md
v <- tryVX variable sColons
w <- variable
return $ A.InCounted m v w
<|> do m <- md
v <- variable
return $ A.InVariable m v
<?> "inputItem"
--}}}
--{{{ variant input (? CASE)
caseInput :: OccParser A.Process
caseInput
= do m <- md
c <- tryVX channel (do {sQuest; sCASE; eol})
indent
vs <- many1 variant
outdent
return $ A.Input m c (A.InputCase m (A.Several m vs))
= do m <- md
c <- tryVX channel (do {sQuest; sCASE; eol})
indent
vs <- many1 variant
outdent
return $ A.Input m c (A.InputCase m (A.Several m vs))
<?> "caseInput"
variant :: OccParser A.Structured
variant
= try (do { m <- md; tl <- taggedList; eol; indent; p <- process; outdent; return $ A.OnlyV m (tl p) })
= do m <- md
tl <- taggedList
eol
indent
p <- process
outdent
return $ A.OnlyV m (tl p)
<|> handleSpecs specification variant A.Spec
<?> "variant"
--}}}
@ -1079,37 +1250,41 @@ variant
output :: OccParser A.Process
output
= channelOutput
<|> do { m <- md; p <- tryVX port sBang; e <- expression; eol; return $ A.Output m p [A.OutExpression m e] }
<|> do m <- md
p <- tryVX port sBang
e <- expression
eol
return $ A.Output m p [A.OutExpression m e]
<?> "output"
channelOutput :: OccParser A.Process
channelOutput
= do m <- md
c <- tryVX channel sBang
-- This is an ambiguity in the occam grammar; you can't tell in "a ! b"
-- whether b is a variable or a tag, without knowing the type of a.
isCase <- typeOfVariable c >>= isCaseProtocolType
if isCase
then
(try (do { t <- tagName; sSemi; os <- sepBy1 outputItem sSemi; eol; return $ A.OutputCase m c t os })
<|> do { t <- tagName; eol; return $ A.OutputCase m c t [] })
else
do { os <- sepBy1 outputItem sSemi; eol; return $ A.Output m c os }
= do m <- md
c <- tryVX channel sBang
-- This is an ambiguity in the occam grammar; you can't tell in "a ! b"
-- whether b is a variable or a tag, without knowing the type of a.
isCase <- typeOfVariable c >>= isCaseProtocolType
if isCase
then
do { t <- tryVX tagName sSemi; os <- sepBy1 outputItem sSemi; eol; return $ A.OutputCase m c t os }
<|> do { t <- tagName; eol; return $ A.OutputCase m c t [] }
else
do { os <- sepBy1 outputItem sSemi; eol; return $ A.Output m c os }
<?> "channelOutput"
outputItem :: OccParser A.OutputItem
outputItem
= try (do { m <- md; a <- intExpr; sColons; b <- expression; return $ A.OutCounted m a b })
= do { m <- md; a <- tryVX intExpr sColons; b <- expression; return $ A.OutCounted m a b }
<|> do { m <- md; e <- expression; return $ A.OutExpression m e }
<?> "outputItem"
--}}}
--{{{ SEQ
seqProcess :: OccParser A.Process
seqProcess
= do m <- md
sSEQ
(do { eol; indent; ps <- many1 process; outdent; return $ A.Seq m ps }
<|> do { r <- replicator; eol; indent; r' <- scopeInRep r; p <- process; scopeOutRep r'; outdent; return $ A.SeqRep m r' p })
= do m <- md
sSEQ
do { eol; indent; ps <- many1 process; outdent; return $ A.Seq m ps }
<|> do { r <- replicator; eol; indent; r' <- scopeInRep r; p <- process; scopeOutRep r'; outdent; return $ A.SeqRep m r' p }
<?> "seqProcess"
--}}}
--{{{ IF
@ -1122,9 +1297,10 @@ ifProcess
conditional :: OccParser A.Structured
conditional
= do { m <- md; sIF ;
do { eol; indent; cs <- many1 ifChoice; outdent; return $ A.Several m cs }
<|> do { r <- replicator; eol; indent; r' <- scopeInRep r; c <- ifChoice; scopeOutRep r'; outdent; return $ A.Rep m r' c } }
= do m <- md
sIF
do { eol; indent; cs <- many1 ifChoice; outdent; return $ A.Several m cs }
<|> do { r <- replicator; eol; indent; r' <- scopeInRep r; c <- ifChoice; scopeOutRep r'; outdent; return $ A.Rep m r' c }
<?> "conditional"
ifChoice :: OccParser A.Structured
@ -1166,8 +1342,20 @@ caseSelector
caseOption :: OccParser A.Structured
caseOption
= try (do { m <- md; ces <- sepBy caseExpression sComma; eol; indent; p <- process; outdent; return $ A.OnlyO m (A.Option m ces p) })
<|> try (do { m <- md; sELSE; eol; indent; p <- process; outdent; return $ A.OnlyO m (A.Else m p) })
= do m <- md
ces <- sepBy caseExpression sComma
eol
indent
p <- process
outdent
return $ A.OnlyO m (A.Option m ces p)
<|> do m <- md
sELSE
eol
indent
p <- process
outdent
return $ A.OnlyO m (A.Else m p)
<|> handleSpecs specification caseOption A.Spec
<?> "option"
@ -1195,26 +1383,32 @@ parallel :: OccParser A.Process
parallel
= do m <- md
isPri <- parKeyword
(do { eol; indent; ps <- many1 process; outdent; return $ A.Par m isPri ps }
<|> do { r <- replicator; eol; indent; r' <- scopeInRep r; p <- process; scopeOutRep r'; outdent; return $ A.ParRep m isPri r' p })
do { eol; indent; ps <- many1 process; outdent; return $ A.Par m isPri ps }
<|> do { r <- replicator; eol; indent; r' <- scopeInRep r; p <- process; scopeOutRep r'; outdent; return $ A.ParRep m isPri r' p }
<|> placedpar
<?> "parallel"
parKeyword :: OccParser A.ParMode
parKeyword
= do { sPAR; return A.PlainPar }
<|> try (do { sPRI; sPAR; return A.PriPar })
<|> do { tryXX sPRI sPAR; return A.PriPar }
<?> "parKeyword"
-- XXX PROCESSOR as a process isn't really legal, surely?
placedpar :: OccParser A.Process
placedpar
= do m <- md
sPLACED
sPAR
(do { eol; indent; ps <- many1 placedpar; outdent; return $ A.Par m A.PlacedPar ps }
<|> do { r <- replicator; eol; indent; r' <- scopeInRep r; p <- placedpar; scopeOutRep r'; outdent; return $ A.ParRep m A.PlacedPar r' p })
<|> do { m <- md; sPROCESSOR; e <- intExpr; eol; indent; p <- process; outdent; return $ A.Processor m e p }
tryXX sPLACED sPAR
do { eol; indent; ps <- many1 placedpar; outdent; return $ A.Par m A.PlacedPar ps }
<|> do { r <- replicator; eol; indent; r' <- scopeInRep r; p <- placedpar; scopeOutRep r'; outdent; return $ A.ParRep m A.PlacedPar r' p }
<|> do m <- md
sPROCESSOR
e <- intExpr
eol
indent
p <- process
outdent
return $ A.Processor m e p
<?> "placedpar"
--}}}
--{{{ ALT
@ -1227,15 +1421,16 @@ altProcess
alternation :: OccParser (Bool, A.Structured)
alternation
= do { m <- md; isPri <- altKeyword ;
do { eol; indent; as <- many1 alternative; outdent; return (isPri, A.Several m as) }
<|> do { r <- replicator; eol; indent; r' <- scopeInRep r; a <- alternative; scopeOutRep r'; outdent; return (isPri, A.Rep m r' a) } }
= do m <- md
isPri <- altKeyword
do { eol; indent; as <- many1 alternative; outdent; return (isPri, A.Several m as) }
<|> do { r <- replicator; eol; indent; r' <- scopeInRep r; a <- alternative; scopeOutRep r'; outdent; return (isPri, A.Rep m r' a) }
<?> "alternation"
altKeyword :: OccParser Bool
altKeyword
= do { sALT; return False }
<|> try (do { sPRI; sALT; return True })
<|> do { tryXX sPRI sALT; return True }
<?> "altKeyword"
-- The reason the CASE guards end up here is because they have to be handled
@ -1243,29 +1438,26 @@ altKeyword
-- are.
alternative :: OccParser A.Structured
alternative
= guardedAlternative
-- FIXME: Check we don't have PRI ALT inside ALT.
<|> do { (isPri, a) <- alternation; return a }
<|> try (do m <- md
b <- booleanExpr
sAmp
c <- channel
sQuest
sCASE
eol
indent
vs <- many1 variant
outdent
return $ A.OnlyA m (A.AlternativeCond m b c (A.InputCase m $ A.Several m vs) (A.Skip m)))
<|> try (do m <- md
c <- channel
sQuest
sCASE
eol
indent
vs <- many1 variant
outdent
return $ A.OnlyA m (A.Alternative m c (A.InputCase m $ A.Several m vs) (A.Skip m)))
= do (isPri, a) <- alternation
return a
-- These are special cases to deal with c ? CASE inside ALTs -- the normal
-- guards are below.
<|> do m <- md
(b, c) <- tryVXVXX booleanExpr sAmp channel sQuest sCASE
eol
indent
vs <- many1 variant
outdent
return $ A.OnlyA m (A.AlternativeCond m b c (A.InputCase m $ A.Several m vs) (A.Skip m))
<|> do m <- md
c <- tryVXX channel sQuest sCASE
eol
indent
vs <- many1 variant
outdent
return $ A.OnlyA m (A.Alternative m c (A.InputCase m $ A.Several m vs) (A.Skip m))
<|> guardedAlternative
<|> handleSpecs specification alternative A.Spec
<?> "alternative"
@ -1281,9 +1473,13 @@ guardedAlternative
guard :: OccParser (A.Process -> A.Alternative)
guard
= try (do { m <- md; (c, im) <- input; return $ A.Alternative m c im })
<|> try (do { m <- md; b <- booleanExpr; sAmp; (c, im) <- input; return $ A.AlternativeCond m b c im })
<|> try (do { m <- md; b <- booleanExpr; sAmp; sSKIP; eol; return $ A.AlternativeSkip m b })
= do m <- md
(c, im) <- input
return $ A.Alternative m c im
<|> do m <- md
b <- tryVX booleanExpr sAmp
do { (c, im) <- input; return $ A.AlternativeCond m b c im }
<|> do { sSKIP; eol; return $ A.AlternativeSkip m b }
<?> "guard"
--}}}
--{{{ PROC calls

View File

@ -31,8 +31,6 @@ The indentation parser is way too simplistic.
Type checks need adding to the parser.
Everything should be converted to commit as soon as possible.
We should have a "current type context" in the parser, so that VAL BYTE b IS 4:
works correctly.