More lenient line feed handling in test expressions.
This commit is contained in:
parent
93140e31a0
commit
e909c8ac42
|
@ -61,7 +61,7 @@ unicodeDoubleQuoteChars = "\x201C\x201D\x2033\x2036"
|
||||||
|
|
||||||
prop_spacing = isOk spacing " \\\n # Comment"
|
prop_spacing = isOk spacing " \\\n # Comment"
|
||||||
spacing = do
|
spacing = do
|
||||||
x <- many (many1 linewhitespace <|> try (string "\\\n"))
|
x <- many (many1 linewhitespace <|> try (string "\\\n" >> return ""))
|
||||||
optional readComment
|
optional readComment
|
||||||
return $ concat x
|
return $ concat x
|
||||||
|
|
||||||
|
@ -270,12 +270,22 @@ readConditionContents single =
|
||||||
parseProblemAt pos WarningC 1009 "Use 'if cmd; then ..' to check exit code, or 'if [[ $(cmd) == .. ]]' to check output.")
|
parseProblemAt pos WarningC 1009 "Use 'if cmd; then ..' to check exit code, or 'if [[ $(cmd) == .. ]]' to check output.")
|
||||||
|
|
||||||
where
|
where
|
||||||
|
spacingOrLf = condSpacing True
|
||||||
|
condSpacing required = do
|
||||||
|
pos <- getPosition
|
||||||
|
space <- allspacing
|
||||||
|
when (required && null space) $
|
||||||
|
parseProblemAt pos ErrorC 1035 "You are missing a required space here."
|
||||||
|
when (single && '\n' `elem` space) $
|
||||||
|
parseProblemAt pos ErrorC 1080 "When breaking lines in [ ], you need \\ before the linefeed."
|
||||||
|
return space
|
||||||
|
|
||||||
typ = if single then SingleBracket else DoubleBracket
|
typ = if single then SingleBracket else DoubleBracket
|
||||||
readCondBinaryOp = try $ do
|
readCondBinaryOp = try $ do
|
||||||
optional guardArithmetic
|
optional guardArithmetic
|
||||||
id <- getNextId
|
id <- getNextId
|
||||||
op <- choice (map tryOp ["==", "!=", "<=", ">=", "=~", ">", "<", "=", "\\<=", "\\>=", "\\<", "\\>"]) <|> otherOp
|
op <- choice (map tryOp ["==", "!=", "<=", ">=", "=~", ">", "<", "=", "\\<=", "\\>=", "\\<", "\\>"]) <|> otherOp
|
||||||
hardCondSpacing
|
spacingOrLf
|
||||||
return op
|
return op
|
||||||
where
|
where
|
||||||
tryOp s = try $ do
|
tryOp s = try $ do
|
||||||
|
@ -308,7 +318,7 @@ readConditionContents single =
|
||||||
readCondUnaryOp = try $ do
|
readCondUnaryOp = try $ do
|
||||||
id <- getNextId
|
id <- getNextId
|
||||||
s <- readOp
|
s <- readOp
|
||||||
hardCondSpacing
|
spacingOrLf
|
||||||
return $ TC_Unary id typ s
|
return $ TC_Unary id typ s
|
||||||
|
|
||||||
readOp = try $ do
|
readOp = try $ do
|
||||||
|
@ -337,19 +347,20 @@ readConditionContents single =
|
||||||
|
|
||||||
readCondAndOp = do
|
readCondAndOp = do
|
||||||
id <- getNextId
|
id <- getNextId
|
||||||
x <- try (string "&&" <|> string "-a")
|
x <- try (readAndOrOp "&&" False <|> readAndOrOp "-a" True)
|
||||||
softCondSpacing
|
|
||||||
skipLineFeeds
|
|
||||||
return $ TC_And id typ x
|
return $ TC_And id typ x
|
||||||
|
|
||||||
readCondOrOp = do
|
readCondOrOp = do
|
||||||
optional guardArithmetic
|
optional guardArithmetic
|
||||||
id <- getNextId
|
id <- getNextId
|
||||||
x <- try (string "||" <|> string "-o")
|
x <- try (readAndOrOp "||" False <|> readAndOrOp "-o" True)
|
||||||
softCondSpacing
|
|
||||||
skipLineFeeds
|
|
||||||
return $ TC_Or id typ x
|
return $ TC_Or id typ x
|
||||||
|
|
||||||
|
readAndOrOp op requiresSpacing = do
|
||||||
|
x <- string op
|
||||||
|
condSpacing requiresSpacing
|
||||||
|
return x
|
||||||
|
|
||||||
readCondNoaryOrBinary = do
|
readCondNoaryOrBinary = do
|
||||||
id <- getNextId
|
id <- getNextId
|
||||||
x <- readCondWord `attempting` (do
|
x <- readCondWord `attempting` (do
|
||||||
|
@ -373,16 +384,21 @@ readConditionContents single =
|
||||||
id <- getNextId
|
id <- getNextId
|
||||||
pos <- getPosition
|
pos <- getPosition
|
||||||
lparen <- try $ string "(" <|> string "\\("
|
lparen <- try $ string "(" <|> string "\\("
|
||||||
when (single && lparen == "(") $ parseProblemAt pos ErrorC 1028 "In [..] you have to escape (). Use [[..]] instead."
|
when (single && lparen == "(") $
|
||||||
when (not single && lparen == "\\(") $ parseProblemAt pos ErrorC 1029 "In [[..]] you shouldn't escape ()."
|
parseProblemAt pos ErrorC 1028 "In [..] you have to escape (). Use [[..]] instead."
|
||||||
if single then hardCondSpacing else disregard spacing
|
when (not single && lparen == "\\(") $
|
||||||
|
parseProblemAt pos ErrorC 1029 "In [[..]] you shouldn't escape ()."
|
||||||
|
condSpacing single
|
||||||
x <- readCondContents
|
x <- readCondContents
|
||||||
cpos <- getPosition
|
cpos <- getPosition
|
||||||
rparen <- string ")" <|> string "\\)"
|
rparen <- string ")" <|> string "\\)"
|
||||||
if single then hardCondSpacing else disregard spacing
|
condSpacing single
|
||||||
when (single && rparen == ")") $ parseProblemAt cpos ErrorC 1030 "In [..] you have to escape (). Use [[..]] instead."
|
when (single && rparen == ")") $
|
||||||
when (not single && rparen == "\\)") $ parseProblemAt cpos ErrorC 1031 "In [[..]] you shouldn't escape ()."
|
parseProblemAt cpos ErrorC 1030 "In [..] you have to escape (). Use [[..]] instead."
|
||||||
when (isEscaped lparen `xor` isEscaped rparen) $ parseProblemAt pos ErrorC 1032 "Did you just escape one half of () but not the other?"
|
when (not single && rparen == "\\)") $
|
||||||
|
parseProblemAt cpos ErrorC 1031 "In [[..]] you shouldn't escape ()."
|
||||||
|
when (isEscaped lparen `xor` isEscaped rparen) $
|
||||||
|
parseProblemAt pos ErrorC 1032 "Did you just escape one half of () but not the other?"
|
||||||
return $ TC_Group id typ x
|
return $ TC_Group id typ x
|
||||||
where
|
where
|
||||||
isEscaped ('\\':_) = True
|
isEscaped ('\\':_) = True
|
||||||
|
@ -426,21 +442,15 @@ readConditionContents single =
|
||||||
str <- string "|"
|
str <- string "|"
|
||||||
return $ T_Literal id str
|
return $ T_Literal id str
|
||||||
|
|
||||||
skipLineFeeds = do
|
|
||||||
pos <- getPosition
|
|
||||||
spacing <- allspacing
|
|
||||||
when (single && '\n' `elem` spacing) $
|
|
||||||
parseProblemAt pos ErrorC 1080 "In [ ] you need \\ before line feeds."
|
|
||||||
|
|
||||||
readCondTerm = do
|
readCondTerm = do
|
||||||
term <- readCondNot <|> readCondExpr
|
term <- readCondNot <|> readCondExpr
|
||||||
skipLineFeeds
|
condSpacing False
|
||||||
return term
|
return term
|
||||||
|
|
||||||
readCondNot = do
|
readCondNot = do
|
||||||
id <- getNextId
|
id <- getNextId
|
||||||
char '!'
|
char '!'
|
||||||
softCondSpacing
|
spacingOrLf
|
||||||
expr <- readCondExpr
|
expr <- readCondExpr
|
||||||
return $ TC_Unary id typ "!" expr
|
return $ TC_Unary id typ "!" expr
|
||||||
|
|
||||||
|
@ -452,7 +462,6 @@ readConditionContents single =
|
||||||
readCondContents = readCondOr
|
readCondContents = readCondOr
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
prop_a1 = isOk readArithmeticContents " n++ + ++c"
|
prop_a1 = isOk readArithmeticContents " n++ + ++c"
|
||||||
prop_a2 = isOk readArithmeticContents "$N*4-(3,2)"
|
prop_a2 = isOk readArithmeticContents "$N*4-(3,2)"
|
||||||
prop_a3 = isOk readArithmeticContents "n|=2<<1"
|
prop_a3 = isOk readArithmeticContents "n|=2<<1"
|
||||||
|
@ -613,7 +622,9 @@ prop_readCondition6 = isOk readCondition "[[ $c =~ ^[yY]$ ]]"
|
||||||
prop_readCondition7 = isOk readCondition "[[ ${line} =~ ^[[:space:]]*# ]]"
|
prop_readCondition7 = isOk readCondition "[[ ${line} =~ ^[[:space:]]*# ]]"
|
||||||
prop_readCondition8 = isOk readCondition "[[ $l =~ ogg|flac ]]"
|
prop_readCondition8 = isOk readCondition "[[ $l =~ ogg|flac ]]"
|
||||||
prop_readCondition9 = isOk readCondition "[ foo -a -f bar ]"
|
prop_readCondition9 = isOk readCondition "[ foo -a -f bar ]"
|
||||||
prop_readCondition10= isOk readCondition "[[ a == b \n || c == d ]]"
|
prop_readCondition10= isOk readCondition "[[\na == b\n||\nc == d ]]"
|
||||||
|
prop_readCondition10a= isOk readCondition "[[\na == b ||\nc == d ]]"
|
||||||
|
prop_readCondition10b= isOk readCondition "[[ a == b\n||\nc == d ]]"
|
||||||
prop_readCondition11= isOk readCondition "[[ a == b ||\n c == d ]]"
|
prop_readCondition11= isOk readCondition "[[ a == b ||\n c == d ]]"
|
||||||
prop_readCondition12= isWarning readCondition "[ a == b \n -o c == d ]"
|
prop_readCondition12= isWarning readCondition "[ a == b \n -o c == d ]"
|
||||||
prop_readCondition13= isOk readCondition "[[ foo =~ ^fo{1,3}$ ]]"
|
prop_readCondition13= isOk readCondition "[[ foo =~ ^fo{1,3}$ ]]"
|
||||||
|
@ -622,9 +633,17 @@ readCondition = called "test expression" $ do
|
||||||
id <- getNextId
|
id <- getNextId
|
||||||
open <- try (string "[[") <|> string "["
|
open <- try (string "[[") <|> string "["
|
||||||
let single = open == "["
|
let single = open == "["
|
||||||
condSpacingMsg False $ if single
|
|
||||||
then "You need spaces after the opening [ and before the closing ]."
|
pos <- getPosition
|
||||||
else "You need spaces after the opening [[ and before the closing ]]."
|
space <- allspacing
|
||||||
|
when (null space) $
|
||||||
|
parseProblemAt pos ErrorC 1035 $ "You need a space after the " ++
|
||||||
|
if single
|
||||||
|
then "[ and before the ]."
|
||||||
|
else "[[ and before the ]]."
|
||||||
|
when (single && '\n' `elem` space) $
|
||||||
|
parseProblemAt pos ErrorC 1080 "You need \\ before line feeds to break lines in [ ]."
|
||||||
|
|
||||||
condition <- readConditionContents single
|
condition <- readConditionContents single
|
||||||
|
|
||||||
cpos <- getPosition
|
cpos <- getPosition
|
||||||
|
@ -635,14 +654,6 @@ readCondition = called "test expression" $ do
|
||||||
many readCmdWord -- Read and throw away remainders to get then/do warnings. Fixme?
|
many readCmdWord -- Read and throw away remainders to get then/do warnings. Fixme?
|
||||||
return $ T_Condition id (if single then SingleBracket else DoubleBracket) condition
|
return $ T_Condition id (if single then SingleBracket else DoubleBracket) condition
|
||||||
|
|
||||||
|
|
||||||
hardCondSpacing = condSpacingMsg False "You need a space here."
|
|
||||||
softCondSpacing = condSpacingMsg True "You need a space here."
|
|
||||||
condSpacingMsg soft msg = do
|
|
||||||
pos <- getPosition
|
|
||||||
space <- spacing
|
|
||||||
when (null space) $ (if soft then parseNoteAt else parseProblemAt) pos ErrorC 1035 msg
|
|
||||||
|
|
||||||
readAnnotationPrefix = do
|
readAnnotationPrefix = do
|
||||||
char '#'
|
char '#'
|
||||||
many linewhitespace
|
many linewhitespace
|
||||||
|
@ -1954,10 +1965,12 @@ g_Rparen = tryToken ")" T_Rparen
|
||||||
g_Bang = do
|
g_Bang = do
|
||||||
id <- getNextId
|
id <- getNextId
|
||||||
char '!'
|
char '!'
|
||||||
softCondSpacing
|
void spacing1 <|> do
|
||||||
|
pos <- getPosition
|
||||||
|
parseProblemAt pos ErrorC 1035
|
||||||
|
"You are missing a required space after the !."
|
||||||
return $ T_Bang id
|
return $ T_Bang id
|
||||||
|
|
||||||
|
|
||||||
g_Semi = do
|
g_Semi = do
|
||||||
notFollowedBy2 g_DSEMI
|
notFollowedBy2 g_DSEMI
|
||||||
tryToken ";" T_Semi
|
tryToken ";" T_Semi
|
||||||
|
|
Loading…
Reference in New Issue