Skip to content

Instantly share code, notes, and snippets.

@erantapaa
Created January 26, 2015 02:09
Show Gist options
  • Save erantapaa/4880fb7e6a623f4fc963 to your computer and use it in GitHub Desktop.
Save erantapaa/4880fb7e6a623f4fc963 to your computer and use it in GitHub Desktop.
alex nested comment example
{
module Nested where
import Control.Monad
}
%wrapper "monadUserState"
$whitespace = [\ \t\b]
$digit = 0-9 -- digits
$alpha = [A-Za-z]
$letter = [a-zA-Z] -- alphabetic characters
$ident = [$letter $digit _] -- identifier character
@number = [$digit]+
@identifier = $alpha($alpha|_|$digit)*
state :-
<0> @identifier { getVariable }
<0> $whitespace+ ;
<0> "/*" { enterNewComment `andBegin` state_comment }
<state_comment> "/*" { embedComment }
<state_comment> "*/" { unembedComment }
<state_comment> . ;
<state_comment> \n { skip }
{
data Token = EOF | ID String
deriving (Show, Eq)
alexEOF :: Alex Token
alexEOF = return EOF
data AlexUserState = AlexUserState
{
-- used by the lexer phase
lexerCommentDepth :: Int
}
alexInitUserState :: AlexUserState
alexInitUserState = AlexUserState 0
getLexerCommentDepth :: Alex Int
getLexerCommentDepth = Alex $ \s@AlexState{alex_ust=ust} -> Right (s, lexerCommentDepth ust)
setLexerCommentDepth :: Int -> Alex ()
setLexerCommentDepth ss = Alex $ \s -> Right (s{alex_ust=(alex_ust s){lexerCommentDepth=ss}}, ())
enterNewComment input len =
do setLexerCommentDepth 1
skip input len
embedComment input len =
do cd <- getLexerCommentDepth
setLexerCommentDepth (cd + 1)
skip input len
unembedComment input len =
do cd <- getLexerCommentDepth
setLexerCommentDepth (cd - 1)
when (cd == 1) (alexSetStartCode state_initial)
skip input len
state_initial :: Int
state_initial = 0
getVariable (p, _, _, input) len = return $ ID s
where
s = take len input
scanner :: String -> Either String [Token]
scanner str =
let loop = do
tok <- alexMonadScan
if tok == EOF
then return []
else do toks <- loop; return (tok:toks)
in runAlex str loop
main = print $ scanner "This /* is */ a /* nested /* comment */ foo */ test"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment