diff --git a/ShellCheck/Parser.hs b/ShellCheck/Parser.hs index 2023157..6539975 100644 --- a/ShellCheck/Parser.hs +++ b/ShellCheck/Parser.hs @@ -1328,7 +1328,12 @@ prop_readDollarExpression1 = isOk readDollarExpression "$(((1) && 3))" prop_readDollarExpression2 = isWarning readDollarExpression "$(((1)) && 3)" prop_readDollarExpression3 = isWarning readDollarExpression "$((\"$@\" &); foo;)" readDollarExpression :: Monad m => SCParser m Token -readDollarExpression = arithmetic <|> readDollarExpansion <|> readDollarBracket <|> readDollarBraceCommandExpansion <|> readDollarBraced <|> readDollarVariable +readDollarExpression = do + -- The grammar should have been designed along the lines of readDollarExpr = char '$' >> stuff, but + -- instead, each subunit parses its own $. This results in ~7 1-3 char lookaheads instead of one 1-char. + -- Instead of optimizing the grammar, here's a green cut that decreases shellcheck runtime by 10%: + lookAhead $ char '$' + arithmetic <|> readDollarExpansion <|> readDollarBracket <|> readDollarBraceCommandExpansion <|> readDollarBraced <|> readDollarVariable where arithmetic = readAmbiguous "$((" readDollarArithmetic readDollarExpansion (\pos -> parseNoteAt pos WarningC 1102 "Shells disambiguate $(( differently or not at all. If the first $( should start command substitution, add a space after it.")