gemini fixes
This commit is contained in:
@@ -3,7 +3,7 @@ module FWL.Parser
|
||||
, parseFile
|
||||
) where
|
||||
|
||||
import Control.Monad (void)
|
||||
import Control.Monad (void, when)
|
||||
import Data.Bits ((.&.), (.|.), shiftL)
|
||||
import Data.List (foldl')
|
||||
import Data.Word (Word8)
|
||||
@@ -15,6 +15,7 @@ import qualified Text.Parsec.Expr as Ex
|
||||
|
||||
import FWL.AST
|
||||
import FWL.Lexer
|
||||
import Data.Char (isUpper)
|
||||
|
||||
-- ─── Entry points ────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -37,7 +38,7 @@ program = do
|
||||
configBlock :: Parser Config
|
||||
configBlock = do
|
||||
reserved "config"
|
||||
props <- braces (semiSep configProp)
|
||||
props <- braces (endBy configProp semi)
|
||||
optional semi
|
||||
return $ foldr applyProp defaultConfig props
|
||||
where
|
||||
@@ -330,13 +331,12 @@ fieldLiteral = try portLit <|> literal
|
||||
n <- fromIntegral <$> natural
|
||||
return (LPort n)
|
||||
|
||||
-- Named pattern reference OR constructor: starts with uppercase-ish ident
|
||||
namedOrCtorPat :: Parser Pat
|
||||
namedOrCtorPat = do
|
||||
n <- identifier
|
||||
args <- optionMaybe (try (parens (commaSep pat)))
|
||||
case args of
|
||||
Nothing -> return (PNamed n) -- bare name = named pattern ref
|
||||
Nothing -> return $ if null n then PWild else if isUpper (head n) then PNamed n else PVar n
|
||||
Just ps -> return (PCtor n ps)
|
||||
|
||||
-- ─── Flow expressions ────────────────────────────────────────────────────────
|
||||
@@ -346,13 +346,17 @@ flowExpr = do
|
||||
first <- FAtom <$> identifier
|
||||
rest <- many (reservedOp "." >> identifier)
|
||||
mw <- optionMaybe (reserved "within" >> durationLit)
|
||||
return $ buildSeq (first : map FAtom rest) mw
|
||||
let chain = buildSeq (first : map FAtom rest)
|
||||
return $ case mw of
|
||||
Nothing -> chain
|
||||
Just w -> attach w chain
|
||||
where
|
||||
buildSeq [x] mw = case mw of
|
||||
Nothing -> x
|
||||
Just w -> FSeq x x (Just w) -- degenerate
|
||||
buildSeq (x:xs) mw = FSeq x (buildSeq xs mw) mw
|
||||
buildSeq [] _ = error "impossible"
|
||||
buildSeq [x] = x
|
||||
buildSeq (x:xs) = FSeq x (buildSeq xs) Nothing
|
||||
buildSeq [] = error "impossible"
|
||||
|
||||
attach w (FSeq a b _) = FSeq a b (Just w)
|
||||
attach w x = FSeq x x (Just w)
|
||||
|
||||
durationLit :: Parser Duration
|
||||
durationLit = do
|
||||
@@ -588,17 +592,18 @@ ipv4Lit_ = do
|
||||
-- Stores as LIP IPv6 (128-bit Integer).
|
||||
ipv6Lit :: Parser Literal
|
||||
ipv6Lit = do
|
||||
(left, right) <- ipv6Groups
|
||||
(left, hasDbl, right) <- ipv6Groups
|
||||
let missing = 8 - length left - length right
|
||||
when (missing < 0) $ fail "too many groups in IPv6 address"
|
||||
when (not hasDbl && missing /= 0) $ fail "invalid IPv6 address (must have 8 groups or use ::)"
|
||||
let groups = left ++ replicate missing 0 ++ right
|
||||
when (length groups /= 8) $ fail "invalid IPv6 address"
|
||||
let val = foldl' (\acc g -> (acc `shiftL` 16) .|. fromIntegral g) (0::Integer) groups
|
||||
return (LIP IPv6 val)
|
||||
|
||||
-- Returns (left-of-::, right-of-::).
|
||||
-- Returns (left-of-::, has_dbl_colon, right-of-::).
|
||||
-- If no :: present, left has all 8 groups and right is empty.
|
||||
ipv6Groups :: Parser ([Int], [Int])
|
||||
ipv6Groups :: Parser ([Int], Bool, [Int])
|
||||
ipv6Groups = do
|
||||
-- must start with a hex digit or ':' (for ::)
|
||||
ahead <- lookAhead (hexDigit <|> char ':')
|
||||
@@ -606,15 +611,15 @@ ipv6Groups = do
|
||||
':' -> do
|
||||
void (string "::")
|
||||
right <- ipv6RightGroups
|
||||
return ([], right)
|
||||
return ([], True, right)
|
||||
_ -> do
|
||||
left <- ipv6LeftGroups
|
||||
mDbl <- optionMaybe (try (string "::"))
|
||||
case mDbl of
|
||||
Nothing -> return (left, [])
|
||||
Nothing -> return (left, False, [])
|
||||
Just _ -> do
|
||||
right <- ipv6RightGroups
|
||||
return (left, right)
|
||||
return (left, True, right)
|
||||
|
||||
-- Parse a run of hex16:hex16:... stopping before :: or end
|
||||
ipv6LeftGroups :: Parser [Int]
|
||||
|
||||
Reference in New Issue
Block a user