gemini fixes

This commit is contained in:
2026-05-03 18:15:59 -07:00
parent a0632d5263
commit 2705f18e0f
5 changed files with 52 additions and 31 deletions

View File

@@ -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]