1 {
2 
3 {-# LANGUAGE OverloadedStrings #-}
4 
5 module Main (main) where
6 import System.Exit
7 import Prelude hiding (lex)
8 
9 import qualified Data.ByteString.Lazy.Char8 as Lazy
10 
11 }
12 
13 %wrapper "monadUserState-bytestring"
14 %token "Token s"
15 %typeclass "Read s"
16 
17 tokens :-
18 
19 [a-b]+$                     { idtoken 0 }
20 [c-d]+/"."                  { idtoken 1 }
21 [e-f]+/{ tokpred }          { idtoken 2 }
22 ^[g-h]+$                    { idtoken 3 }
23 ^[i-j]+/"."                 { idtoken 4 }
24 ^[k-l]+/{ tokpred }         { idtoken 5 }
25 [m-n]+$                     { idtoken 6 }
26 [o-p]+/"."                  { idtoken 7 }
27 [q-r]+/{ tokpred }          { idtoken 8 }
28 [0-1]^[s-t]+$               { idtoken 9 }
29 [2-3]^[u-v]+/"."            { idtoken 10 }
30 [4-5]^[w-x]+/{ tokpred }    { idtoken 11 }
31 [y-z]+                      { idtoken 12 }
32 [A-B]+$                     ;
33 [C-D]+/"."                  ;
34 [E-F]+/{ tokpred }          ;
35 ^[G-H]+$                    ;
36 ^[I-J]+/"."                 ;
37 ^[K-L]+/{ tokpred }         ;
38 [M-N]+$                     ;
39 [O-P]+/"."                  ;
40 [Q-R]+/{ tokpred }          ;
41 [0-1]^[S-T]+$               ;
42 [2-3]^[U-V]+/"."            ;
43 [4-5]^[W-X]+/{ tokpred }    ;
44 [Y-Z]+                      ;
45 \.                          ;
46 [ \n\t\r]+                  ;
47 [0-9]                       ;
48 
49 {
50 
51 type AlexUserState = Int
52 
53 alexInitUserState = 0
54 
55 alexEOF :: Alex (Token s)
56 alexEOF = return EOF
57 
58 tokpred :: AlexUserState -> AlexInput -> Int -> AlexInput -> Bool
59 tokpred _ _ _ _ = True
60 
61 idtoken :: Read s => Int -> AlexInput -> Int64 -> Alex (Token s)
62 idtoken n (_, _, s, _) len =
63   return (Id n (read ("\"" ++ Lazy.unpack (Lazy.take (fromIntegral len) s) ++
64                       "\"")))
65 
66 data Token s = Id Int s | EOF deriving Eq
67 
68 lex :: Read s => Lazy.ByteString -> Either String [Token s]
69 lex inp =
70   let
71     lexAll =
72       do
73         res <- alexMonadScan
74         case res of
75           EOF -> return []
76           tok ->
77             do
78               rest <- lexAll
79               return (tok : rest)
80   in
81     runAlex inp lexAll
82 
83 input = "abab\ndddc.fff\ngh\nijji.\nllmnm\noop.rq0tsst\n3uuvu.5xxw"
84 
85 tokens = [ Id 0 "abab", Id 1 "dddc", Id 2 "fff", Id 3 "gh", Id 4 "ijji",
86            Id 5 "ll", Id 6 "mnm", Id 7 "oop", Id 8 "rq", Id 9 "tsst",
87            Id 10 "uuvu", Id 11 "xxw"]
88 
89 main :: IO ()
90 main =
91   let
92     result :: Either String [Token String]
93     result = lex input
94   in do
95     case result of
96       Left _ -> exitFailure
97       Right toks ->
98         do
99           if toks /= tokens
100             then exitFailure
101             else exitWith ExitSuccess
102 
103 }
104