|
@ -35,12 +35,13 @@ tokens :- |
|
|
$white_nol+ ; |
|
|
$white_nol+ ; |
|
|
\t { \_ _ -> alexError "tab character in source code" } |
|
|
\t { \_ _ -> alexError "tab character in source code" } |
|
|
|
|
|
|
|
|
<0,import_> "--" .* \n |
|
|
|
|
|
|
|
|
<0,import_,foreign_> "--" .* \n |
|
|
{ just $ pushStartCode newline } |
|
|
{ just $ pushStartCode newline } |
|
|
|
|
|
|
|
|
<0> \= { always TokEqual } |
|
|
<0> \= { always TokEqual } |
|
|
<0> \` { always TokTick } |
|
|
<0> \` { always TokTick } |
|
|
<0> \: \: { always TokDoubleColon } |
|
|
<0> \: \: { always TokDoubleColon } |
|
|
|
|
|
<foreign_> \: \: { \i l -> popStartCode *> always TokDoubleColon i l } |
|
|
|
|
|
|
|
|
<0> \\ { \i l -> setPendingLC *> yield' (const TokLambda) i l } |
|
|
<0> \\ { \i l -> setPendingLC *> yield' (const TokLambda) i l } |
|
|
<0> "->" { always TokArrow } |
|
|
<0> "->" { always TokArrow } |
|
@ -49,7 +50,7 @@ tokens :- |
|
|
<0> \{ { always TokOBrace } |
|
|
<0> \{ { always TokOBrace } |
|
|
<0> \[ { always TokOSquare } |
|
|
<0> \[ { always TokOSquare } |
|
|
|
|
|
|
|
|
<0,import_> { |
|
|
|
|
|
|
|
|
<0,import_,foreign_> { |
|
|
\, { always TokComma } |
|
|
\, { always TokComma } |
|
|
\( { always TokOParen } |
|
|
\( { always TokOParen } |
|
|
\) { always TokCParen } |
|
|
\) { always TokCParen } |
|
@ -60,9 +61,9 @@ tokens :- |
|
|
|
|
|
|
|
|
<0> \;+ { always TokSemi } |
|
|
<0> \;+ { always TokSemi } |
|
|
|
|
|
|
|
|
<0,import_> \n { just $ pushStartCode newline } |
|
|
|
|
|
|
|
|
<0,import_,foreign_> \n { just $ pushStartCode newline } |
|
|
|
|
|
|
|
|
<0> \" { startString } |
|
|
|
|
|
|
|
|
<0,foreign_> \" { startString } |
|
|
|
|
|
|
|
|
<string> { |
|
|
<string> { |
|
|
\\ \" { stringAppend (T.singleton '"') } |
|
|
\\ \" { stringAppend (T.singleton '"') } |
|
@ -107,17 +108,12 @@ tokens :- |
|
|
() { startLayout } |
|
|
() { startLayout } |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
<import_> { |
|
|
|
|
|
\n { just $ pushStartCode newline } |
|
|
|
|
|
"--" .* \n { just $ pushStartCode newline } |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
<empty_layout> () { emptyLayout } |
|
|
<empty_layout> () { emptyLayout } |
|
|
|
|
|
|
|
|
<pending> () { emitPendingToken } |
|
|
<pending> () { emitPendingToken } |
|
|
|
|
|
|
|
|
-- identifiers and keywords |
|
|
-- identifiers and keywords |
|
|
<0,import_> { |
|
|
|
|
|
|
|
|
<0,import_,foreign_> { |
|
|
$lower [$alpha $digit \_ \']* { variableOrKeyword } |
|
|
$lower [$alpha $digit \_ \']* { variableOrKeyword } |
|
|
$upper [$alpha $digit \_ \']* { yield (TokUnqual ConId) } |
|
|
$upper [$alpha $digit \_ \']* { yield (TokUnqual ConId) } |
|
|
|
|
|
|
|
@ -300,7 +296,7 @@ offsideRule (Posn line col, _, _, _) _ = do |
|
|
maybePopImportSC :: Alex () |
|
|
maybePopImportSC :: Alex () |
|
|
maybePopImportSC = do |
|
|
maybePopImportSC = do |
|
|
startcode <- alexGetStartCode |
|
|
startcode <- alexGetStartCode |
|
|
when (startcode == import_) popStartCode |
|
|
|
|
|
|
|
|
when (startcode == import_ || startcode == foreign_) popStartCode |
|
|
|
|
|
|
|
|
emptyLayout :: AlexInput -> Int64 -> Alex Token |
|
|
emptyLayout :: AlexInput -> Int64 -> Alex Token |
|
|
emptyLayout (Posn line col, _, _, _) _ = do |
|
|
emptyLayout (Posn line col, _, _, _) _ = do |
|
@ -402,18 +398,20 @@ finishVarKw l c text = do |
|
|
-- set the "keyword" (now changed to an identifier) as pending, so |
|
|
-- set the "keyword" (now changed to an identifier) as pending, so |
|
|
-- that it will be emitted by the next alexMonadScan. |
|
|
-- that it will be emitted by the next alexMonadScan. |
|
|
"import" -> do |
|
|
"import" -> do |
|
|
pushStartCode import_ |
|
|
|
|
|
|
|
|
when ((sc /= import_) && (sc /= foreign_)) $ pushStartCode import_ |
|
|
pure (Token TokImport l c) |
|
|
pure (Token TokImport l c) |
|
|
|
|
|
|
|
|
"as" |
|
|
|
|
|
| sc == import_, c > col -> pure (Token TokAs l c) |
|
|
|
|
|
| sc == import_ -> offsideKeyword (TokUnqual VarId text) l c |
|
|
|
|
|
| otherwise -> pure (Token (TokUnqual VarId text) l c) |
|
|
|
|
|
|
|
|
"as" -> conditionalKeyword l c import_ (c > col) TokAs |
|
|
|
|
|
"qualified" -> conditionalKeyword l c import_ (c > col) TokQualified |
|
|
|
|
|
|
|
|
"qualified" |
|
|
|
|
|
| sc == import_, c > col -> pure (Token TokQualified l c) |
|
|
|
|
|
| sc == import_ -> offsideKeyword (TokUnqual VarId text) l c |
|
|
|
|
|
| otherwise -> pure (Token (TokUnqual VarId text) l c) |
|
|
|
|
|
|
|
|
"foreign" -> do |
|
|
|
|
|
when (sc /= foreign_) $ pushStartCode foreign_ |
|
|
|
|
|
pure (Token TokForeign l c) |
|
|
|
|
|
|
|
|
|
|
|
"export" -> conditionalKeyword l c foreign_ (c > col) TokForeign |
|
|
|
|
|
"safe" -> conditionalKeyword l c foreign_ (c > col) TokSafe |
|
|
|
|
|
"unsafe" -> conditionalKeyword l c foreign_ (c > col) TokUnsafe |
|
|
|
|
|
"ccall" -> conditionalKeyword l c foreign_ (c > col) TokCCall |
|
|
|
|
|
|
|
|
-- when starting a layout context for let expressions we make sure |
|
|
-- when starting a layout context for let expressions we make sure |
|
|
-- that it is distinguishable from layout contexts started by |
|
|
-- that it is distinguishable from layout contexts started by |
|
@ -456,6 +454,15 @@ finishVarKw l c text = do |
|
|
|
|
|
|
|
|
[] -> error "empty keyword/identifier" |
|
|
[] -> error "empty keyword/identifier" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conditionalKeyword l c import_ cond kw = do |
|
|
|
|
|
sc <- alexGetStartCode |
|
|
|
|
|
case () of |
|
|
|
|
|
() | sc == import_, cond -> pure (Token kw l c) |
|
|
|
|
|
| sc == import_ -> offsideKeyword (TokUnqual VarId text) l c |
|
|
|
|
|
| otherwise -> pure (Token (TokUnqual VarId text) l c) |
|
|
|
|
|
where text = T.pack (show kw) |
|
|
|
|
|
|
|
|
finishVar :: (IdClass -> T.Text -> TokenClass) -> (IdClass -> T.Text -> T.Text -> TokenClass) -> Int -> Int -> T.Text -> Alex Token |
|
|
finishVar :: (IdClass -> T.Text -> TokenClass) -> (IdClass -> T.Text -> T.Text -> TokenClass) -> Int -> Int -> T.Text -> Alex Token |
|
|
finishVar tokunqual tokqual l c text |
|
|
finishVar tokunqual tokqual l c text |
|
|
| T.null text = undefined |
|
|
| T.null text = undefined |
|
|