diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..da90f91 --- /dev/null +++ b/.gitignore @@ -0,0 +1,37 @@ +*.hi +*.prof +*~ +*.o +*.info +/AlexTemplate-debug.bak +/AlexTemplate-ghc-debug.bak +/AlexTemplate-ghc.bak +/AlexTemplate.bak +/AlexWrapper-basic-bytestring.bak +/AlexWrapper-basic.bak +/AlexWrapper-gscan.bak +/AlexWrapper-monad-bytestring.bak +/AlexWrapper-monad.bak +/AlexWrapper-monadUserState-bytestring.bak +/AlexWrapper-monadUserState.bak +/AlexWrapper-posn-bytestring.bak +/AlexWrapper-posn.bak +/AlexWrapper-strict-bytestring.bak +/AlexTemplate +/AlexTemplate-debug +/AlexTemplate-ghc +/AlexTemplate-ghc-debug +/AlexWrapper-basic +/AlexWrapper-basic-bytestring +/AlexWrapper-gscan +/AlexWrapper-monad +/AlexWrapper-monad-bytestring +/AlexWrapper-monadUserState +/AlexWrapper-monadUserState-bytestring +/AlexWrapper-posn +/AlexWrapper-posn-bytestring +/AlexWrapper-strict-bytestring +/dist +/src/Data/Ranged/Boundaries.hs~ +/src/Data/Ranged/RangedSet.hs~ +/src/Data/Ranged/Ranges.hs~ diff --git a/NOTE.txt b/NOTE.txt new file mode 100644 index 0000000..6a92a0c --- /dev/null +++ b/NOTE.txt @@ -0,0 +1,9 @@ +Note: + +The contents of package Ranged-sets-0.3.0 has been copied into this +package, in order to allow it to be part of the Haskell Platform, +without introducing additional dependencies. + +The original license agreement has been included in the src/Data +subdirectory, as required by the package source. + diff --git a/alex.cabal b/alex.cabal index d04467b..355549a 100644 --- a/alex.cabal +++ b/alex.cabal @@ -10,15 +10,9 @@ stability: stable homepage: http://www.haskell.org/alex/ synopsis: Alex is a tool for generating lexical analysers in Haskell category: Development -cabal-version: >= 1.2 - --- Later, this isn't compatible with Cabal 1.2: --- source-repository head --- type: darcs --- location: http://darcs.haskell.org/alex/ - - +cabal-version: >= 1.6 build-type: Custom + extra-source-files: ANNOUNCE README @@ -58,6 +52,10 @@ extra-source-files: tests/tokens_gscan.x tests/tokens_posn.x +source-repository head + type: git + location: http://darcs.haskell.org/alex.git + flag small_base description: Choose the new smaller, split-up base package. @@ -71,13 +69,16 @@ executable alex build-depends: base >= 1.0 build-depends: base < 5 + -- build-depends: Ranged-sets + build-depends: QuickCheck >=2 extensions: CPP - ghc-options: -Wall + ghc-options: -Wall -rtsopts other-modules: AbsSyn CharSet DFA + DFAMin DFS Info Main @@ -90,3 +91,4 @@ executable alex Set Sort Util + UTF8 diff --git a/src/AbsSyn.hs b/src/AbsSyn.hs index 21d7c0d..ac5331e 100644 --- a/src/AbsSyn.hs +++ b/src/AbsSyn.hs @@ -23,6 +23,7 @@ module AbsSyn ( import CharSet ( CharSet ) import Map ( Map ) import qualified Map hiding ( Map ) +import Data.IntMap (IntMap) import Sort ( nub' ) import Util ( str, nl ) @@ -66,6 +67,7 @@ data RightContext r = NoRightContext | RightContextRExp r | RightContextCode Code + deriving (Eq,Ord) instance Show RECtx where showsPrec _ (RECtx scs _ r rctx code) = @@ -95,16 +97,19 @@ data DFA s a = DFA dfa_states :: Map s (State s a) } -data State s a = State [Accept a] (Map Char s) +data State s a = State { state_acc :: [Accept a], + state_out :: IntMap s -- 0..255 only + } type SNum = Int data Accept a = Acc { accPrio :: Int, accAction :: Maybe a, - accLeftCtx :: Maybe CharSet, + accLeftCtx :: Maybe CharSet, -- cannot be converted to byteset at this point. accRightCtx :: RightContext SNum } + deriving (Eq,Ord) -- debug stuff instance Show (Accept a) where diff --git a/src/CharSet.hs b/src/CharSet.hs index 4cb8388..06963f6 100644 --- a/src/CharSet.hs +++ b/src/CharSet.hs @@ -11,6 +11,16 @@ -- ----------------------------------------------------------------------------} module CharSet ( + setSingleton, + + Encoding(..), + + Byte, + ByteSet, + byteSetSingleton, + byteRanges, + byteSetRange, + CharSet, -- abstract emptyCharSet, charSetSingleton, @@ -19,39 +29,141 @@ module CharSet ( charSetComplement, charSetRange, charSetUnion, - charSetToArray, - charSetElems + charSetQuote, + setUnions, + byteSetToArray, + byteSetElems, + byteSetElem ) where -import Data.Array ( Array, array ) +import Data.Array +import Data.Ranged +import Data.Word +import Data.Maybe (catMaybes) +import Data.Char (chr,ord) +import UTF8 +type Byte = Word8 -- Implementation as functions -type CharSet = Char -> Bool +type CharSet = RSet Char +type ByteSet = RSet Byte +-- type Utf8Set = RSet [Byte] +type Utf8Range = Span [Byte] + +data Encoding = Latin1 | UTF8 emptyCharSet :: CharSet -emptyCharSet = const False +emptyCharSet = rSetEmpty + +byteSetElem :: ByteSet -> Byte -> Bool +byteSetElem = rSetHas charSetSingleton :: Char -> CharSet -charSetSingleton c = \x -> x == c +charSetSingleton = rSingleton + +setSingleton :: DiscreteOrdered a => a -> RSet a +setSingleton = rSingleton charSet :: [Char] -> CharSet -charSet s x = x `elem` s +charSet = setUnions . fmap charSetSingleton charSetMinus :: CharSet -> CharSet -> CharSet -charSetMinus s1 s2 x = s1 x && not (s2 x) +charSetMinus = rSetDifference charSetUnion :: CharSet -> CharSet -> CharSet -charSetUnion s1 s2 x = s1 x || s2 x +charSetUnion = rSetUnion + +setUnions :: DiscreteOrdered a => [RSet a] -> RSet a +setUnions = foldr rSetUnion rSetEmpty charSetComplement :: CharSet -> CharSet -charSetComplement s1 = not . s1 +charSetComplement = rSetNegation charSetRange :: Char -> Char -> CharSet -charSetRange c1 c2 x = x >= c1 && x <= c2 +charSetRange c1 c2 = makeRangedSet [Range (BoundaryBelow c1) (BoundaryAbove c2)] + +byteSetToArray :: ByteSet -> Array Byte Bool +byteSetToArray set = array (fst (head ass), fst (last ass)) ass + where ass = [(c,rSetHas set c) | c <- [0..0xff]] + +byteSetElems :: ByteSet -> [Byte] +byteSetElems set = [c | c <- [0 .. 0xff], rSetHas set c] + +charToRanges :: Encoding -> CharSet -> [Utf8Range] +charToRanges Latin1 = + map (fmap ((: []).fromIntegral.ord)) -- Span [Byte] + . catMaybes + . fmap (charRangeToCharSpan False) + . rSetRanges +charToRanges UTF8 = + concat -- Span [Byte] + . fmap toUtfRange -- [Span [Byte]] + . fmap (fmap UTF8.encode) -- Span [Byte] + . catMaybes + . fmap (charRangeToCharSpan True) + . rSetRanges + +-- | Turns a range of characters expressed as a pair of UTF-8 byte sequences into a set of ranges, in which each range of the resulting set is between pairs of sequences of the same length +toUtfRange :: Span [Byte] -> [Span [Byte]] +toUtfRange (Span x y) = fix x y + +fix :: [Byte] -> [Byte] -> [Span [Byte]] +fix x y + | length x == length y = [Span x y] + | length x == 1 = Span x [0x7F] : fix [0xC2,0x80] y + | length x == 2 = Span x [0xDF,0xBF] : fix [0xE0,0x80,0x80] y + | length x == 3 = Span x [0xEF,0xBF,0xBF] : fix [0xF0,0x80,0x80,0x80] y + | otherwise = error "fix: incorrect input given" + + +byteRangeToBytePair :: Span [Byte] -> ([Byte],[Byte]) +byteRangeToBytePair (Span x y) = (x,y) + +data Span a = Span a a -- lower bound inclusive, higher bound exclusive + -- (SDM: upper bound inclusive, surely??) +instance Functor Span where + fmap f (Span x y) = Span (f x) (f y) + +charRangeToCharSpan :: Bool -> Range Char -> Maybe (Span Char) +charRangeToCharSpan _ (Range BoundaryAboveAll _) = Nothing +charRangeToCharSpan _ (Range _ BoundaryBelowAll) = Nothing +charRangeToCharSpan uni (Range x y) = Just (Span (l x) (h y)) + where l b = case b of + BoundaryBelowAll -> '\0' + BoundaryBelow a -> a + BoundaryAbove a -> succ a + BoundaryAboveAll -> error "panic: charRangeToCharSpan" + h b = case b of + BoundaryBelowAll -> error "panic: charRangeToCharSpan" + BoundaryBelow a -> pred a + BoundaryAbove a -> a + BoundaryAboveAll | uni -> chr 0x10ffff + | otherwise -> chr 0xff + +byteRanges :: Encoding -> CharSet -> [([Byte],[Byte])] +byteRanges enc = fmap byteRangeToBytePair . charToRanges enc + +byteSetRange :: Byte -> Byte -> ByteSet +byteSetRange c1 c2 = makeRangedSet [Range (BoundaryBelow c1) (BoundaryAbove c2)] + +byteSetSingleton :: Byte -> ByteSet +byteSetSingleton = rSingleton + +instance DiscreteOrdered Word8 where + adjacent x y = x + 1 == y + adjacentBelow 0 = Nothing + adjacentBelow x = Just (x-1) -charSetToArray :: CharSet -> Array Char Bool -charSetToArray set = array (fst (head ass), fst (last ass)) ass - where ass = [(c,set c) | c <- ['\0'..'\xff']] +-- TODO: More efficient generated code! +charSetQuote :: CharSet -> String +charSetQuote s = "(\\c -> " ++ foldr (\x y -> x ++ " || " ++ y) "False" (map quoteRange (rSetRanges s)) ++ ")" + where quoteRange (Range l h) = quoteL l ++ " && " ++ quoteH h + quoteL (BoundaryAbove a) = "c > " ++ show a + quoteL (BoundaryBelow a) = "c >= " ++ show a + quoteL (BoundaryAboveAll) = "False" + quoteL (BoundaryBelowAll) = "True" + quoteH (BoundaryAbove a) = "c <= " ++ show a + quoteH (BoundaryBelow a) = "c < " ++ show a + quoteH (BoundaryAboveAll) = "True" + quoteH (BoundaryBelowAll) = "False" -charSetElems :: CharSet -> [Char] -charSetElems set = [c | c <- ['\0'..'\xff'], set c] diff --git a/src/DFA.hs b/src/DFA.hs index 73c19cf..11076b2 100644 --- a/src/DFA.hs +++ b/src/DFA.hs @@ -17,6 +17,7 @@ module DFA(scanner2dfa) where import AbsSyn import qualified Map +import qualified Data.IntMap as IntMap import NFA import Sort ( msort, nub' ) import CharSet @@ -88,8 +89,8 @@ type StartCode = Int -- state of the partial DFA, until all possible state sets have been considered -- The final DFA is then constructed with a `mk_dfa'. -scanner2dfa:: Scanner -> [StartCode] -> DFA SNum Code -scanner2dfa scanner scs = nfa2dfa scs (scanner2nfa scanner scs) +scanner2dfa:: Encoding -> Scanner -> [StartCode] -> DFA SNum Code +scanner2dfa enc scanner scs = nfa2dfa scs (scanner2nfa enc scanner scs) nfa2dfa:: [StartCode] -> NFA -> DFA SNum Code nfa2dfa scs nfa = mk_int_dfa nfa (nfa2pdfa nfa pdfa (dfa_start_states pdfa)) @@ -110,30 +111,27 @@ nfa2pdfa nfa pdfa (ss:umkd) | ss `in_pdfa` pdfa = nfa2pdfa nfa pdfa umkd | otherwise = nfa2pdfa nfa pdfa' umkd' where - pdfa' = add_pdfa ss (State accs (Map.fromList ss_outs)) pdfa + pdfa' = add_pdfa ss (State accs (IntMap.fromList ss_outs)) pdfa umkd' = rctx_sss ++ map snd ss_outs ++ umkd -- for each character, the set of states that character would take -- us to from the current set of states in the NFA. - ss_outs :: [(Char, StateSet)] - ss_outs = [ (ch, mk_ss nfa ss') - | ch <- dfa_alphabet, - let ss' = [ s' | (p,s') <- outs, p ch ], - not (null ss') - ] + ss_outs :: [(Int, StateSet)] + ss_outs = [ (fromIntegral ch, mk_ss nfa ss') + | ch <- byteSetElems $ setUnions [p | (p,_) <- outs], + let ss' = [ s' | (p,s') <- outs, byteSetElem p ch ], + not (null ss') + ] rctx_sss = [ mk_ss nfa [s] | Acc _ _ _ (RightContextRExp s) <- accs ] - outs :: [(CharSet,SNum)] + outs :: [(ByteSet,SNum)] outs = [ out | s <- ss, out <- nst_outs (nfa!s) ] accs = sort_accs [acc| s<-ss, acc<-nst_accs (nfa!s)] -dfa_alphabet:: [Char] -dfa_alphabet = ['\0'..'\255'] - -- `sort_accs' sorts a list of accept values into decending order of priority, -- eliminating any elements that follow an unconditional accept value. @@ -198,7 +196,7 @@ mk_int_dfa nfa (DFA start_states mp) cnv :: State StateSet a -> State SNum a cnv (State accs as) = State accs' as' where - as' = Map.mapWithKey (\_ch s -> lookup' s) as + as' = IntMap.mapWithKey (\_ch s -> lookup' s) as accs' = map cnv_acc accs cnv_acc (Acc p a lctx rctx) = Acc p a lctx rctx' diff --git a/src/DFAMin.hs b/src/DFAMin.hs new file mode 100644 index 0000000..8302346 --- /dev/null +++ b/src/DFAMin.hs @@ -0,0 +1,150 @@ +{-# OPTIONS_GHC -fno-warn-name-shadowing #-} +{-# LANGUAGE PatternGuards #-} +module DFAMin (minimizeDFA) where + +import AbsSyn + +import Data.Map (Map) +import qualified Data.Map as Map +import Data.IntSet (IntSet) +import qualified Data.IntSet as IS +import Data.IntMap (IntMap) +import qualified Data.IntMap as IM +import Data.List as List + + +-- Hopcroft's Algorithm for DFA minimization (cut/pasted from Wikipedia): + +-- P := {{all accepting states}, {all nonaccepting states}}; +-- Q := {{all accepting states}}; +-- while (Q is not empty) do +-- choose and remove a set A from Q +-- for each c in ∑ do +-- let X be the set of states for which a transition on c leads to a state in A +-- for each set Y in P for which X ∩ Y is nonempty do +-- replace Y in P by the two sets X ∩ Y and Y \ X +-- if Y is in Q +-- replace Y in Q by the same two sets +-- else +-- add the smaller of the two sets to Q +-- end; +-- end; +-- end; + +minimizeDFA :: Ord a => DFA Int a -> DFA Int a +minimizeDFA dfa@ DFA { dfa_start_states = starts, + dfa_states = statemap + } + = DFA { dfa_start_states = starts, + dfa_states = Map.fromList states } + where + equiv_classes = groupEquivStates dfa + + numbered_states = number (length starts) equiv_classes + + -- assign each state in the minimized DFA a number, making + -- sure that we assign the numbers [0..] to the start states. + number _ [] = [] + number n (ss:sss) = + case filter (`IS.member` ss) starts of + [] -> (n,ss) : number (n+1) sss + starts' -> zip starts' (repeat ss) ++ number n sss + -- if one of the states of the minimized DFA corresponds + -- to multiple starts states, we just have to duplicate + -- that state. + + states = [ + let old_states = map (lookup statemap) (IS.toList equiv) + accs = map fix_acc (state_acc (head old_states)) + -- accepts should all be the same + out = IM.fromList [ (b, get_new old) + | State _ out <- old_states, + (b,old) <- IM.toList out ] + in (n, State accs out) + | (n, equiv) <- numbered_states + ] + + fix_acc acc = acc { accRightCtx = fix_rctxt (accRightCtx acc) } + + fix_rctxt (RightContextRExp s) = RightContextRExp (get_new s) + fix_rctxt other = other + + lookup m k = Map.findWithDefault (error "minimizeDFA") k m + get_new = lookup old_to_new + + old_to_new :: Map Int Int + old_to_new = Map.fromList [ (s,n) | (n,ss) <- numbered_states, + s <- IS.toList ss ] + + +groupEquivStates :: (Ord a) => DFA Int a -> [IntSet] +groupEquivStates DFA { dfa_states = statemap } + = go init_p init_q + where + (accepting, nonaccepting) = Map.partition acc statemap + where acc (State as _) = not (List.null as) + + nonaccepting_states = IS.fromList (Map.keys nonaccepting) + + -- group the accepting states into equivalence classes + accept_map = {-# SCC "accept_map" #-} + foldl' (\m (n,s) -> Map.insertWith (++) (state_acc s) [n] m) + Map.empty + (Map.toList accepting) + + -- accept_groups :: Ord s => [Set s] + accept_groups = map IS.fromList (Map.elems accept_map) + + init_p = nonaccepting_states : accept_groups + init_q = accept_groups + + -- map token T to + -- a map from state S to the list of states that transition to + -- S on token T + -- This is a cache of the information needed to compute x below + bigmap :: IntMap (IntMap [SNum]) + bigmap = IM.fromListWith (IM.unionWith (++)) + [ (i, IM.singleton to [from]) + | (from, state) <- Map.toList statemap, + (i,to) <- IM.toList (state_out state) ] + + -- incoming I A = the set of states that transition to a state in + -- A on token I. + incoming :: Int -> IntSet -> IntSet + incoming i a = IS.fromList (concat ss) + where + map1 = IM.findWithDefault (error "go1") i bigmap + ss = [ IM.findWithDefault [] s map1 + | s <- IS.toList a ] + + -- The outer loop: recurse on each set in Q + go p [] = p + go p (a:q) = go1 0 p q + where + -- recurse on each token (0..255) + go1 256 p q = go p q + go1 i p q = go1 (i+1) p' q' + where + (p',q') = go2 p [] q + + x = incoming i a + + -- recurse on each set in P + go2 [] p' q = (p',q) + go2 (y:p) p' q + | IS.null i || IS.null d = go2 p (y:p') q + | otherwise = go2 p (i:d:p') q1 + where + i = IS.intersection x y + d = IS.difference y x + + q1 = replaceyin q + where + replaceyin [] = + if IS.size i < IS.size d then [i] else [d] + replaceyin (z:zs) + | z == y = i : d : zs + | otherwise = z : replaceyin zs + + + diff --git a/src/Data/LICENSE.txt b/src/Data/LICENSE.txt new file mode 100644 index 0000000..cc3db97 --- /dev/null +++ b/src/Data/LICENSE.txt @@ -0,0 +1,30 @@ +Copyright (c) 2005, Paul Johnson +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of the Ranged Sets project nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/src/Data/Ranged.hs b/src/Data/Ranged.hs new file mode 100644 index 0000000..2242485 --- /dev/null +++ b/src/Data/Ranged.hs @@ -0,0 +1,9 @@ +module Data.Ranged ( + module Data.Ranged.Boundaries, + module Data.Ranged.Ranges, + module Data.Ranged.RangedSet +) where + +import Data.Ranged.Boundaries +import Data.Ranged.Ranges +import Data.Ranged.RangedSet diff --git a/src/Data/Ranged/Boundaries.hs b/src/Data/Ranged/Boundaries.hs new file mode 100644 index 0000000..67eb696 --- /dev/null +++ b/src/Data/Ranged/Boundaries.hs @@ -0,0 +1,229 @@ +----------------------------------------------------------------------------- +-- | +-- Module : Data.Ranged.Boundaries +-- Copyright : (c) Paul Johnson 2006 +-- License : BSD-style +-- Maintainer : paul@cogito.org.uk +-- Stability : experimental +-- Portability : portable +-- +----------------------------------------------------------------------------- + +module Data.Ranged.Boundaries ( + DiscreteOrdered (..), + enumAdjacent, + boundedAdjacent, + boundedBelow, + Boundary (..), + above, + (/>/) +) where + +import Data.Ratio +import Test.QuickCheck + +infix 4 />/ + +{- | +Distinguish between dense and sparse ordered types. A dense type is +one in which any two values @v1 < v2@ have a third value @v3@ such that +@v1 < v3 < v2@. + +In theory the floating types are dense, although in practice they can only have +finitely many values. This class treats them as dense. + +Tuples up to 4 members are declared as instances. Larger tuples may be added +if necessary. + +Most values of sparse types have an @adjacentBelow@, such that, for all x: + +> case adjacentBelow x of +> Just x1 -> adjacent x1 x +> Nothing -> True + +The exception is for bounded types when @x == lowerBound@. For dense types +@adjacentBelow@ always returns 'Nothing'. + +This approach was suggested by Ben Rudiak-Gould on comp.lang.functional. +-} + +class Ord a => DiscreteOrdered a where + -- | Two values @x@ and @y@ are adjacent if @x < y@ and there does not + -- exist a third value between them. Always @False@ for dense types. + adjacent :: a -> a -> Bool + -- | The value immediately below the argument, if it can be determined. + adjacentBelow :: a -> Maybe a + + +-- Implementation note: the precise rules about unbounded enumerated vs +-- bounded enumerated types are difficult to express using Haskell 98, so +-- the prelude types are listed individually here. + +instance DiscreteOrdered Bool where + adjacent = boundedAdjacent + adjacentBelow = boundedBelow + +instance DiscreteOrdered Ordering where + adjacent = boundedAdjacent + adjacentBelow = boundedBelow + +instance DiscreteOrdered Char where + adjacent = boundedAdjacent + adjacentBelow = boundedBelow + +instance DiscreteOrdered Int where + adjacent = boundedAdjacent + adjacentBelow = boundedBelow + +instance DiscreteOrdered Integer where + adjacent = enumAdjacent + adjacentBelow = Just . pred + +instance DiscreteOrdered Double where + adjacent _ _ = False + adjacentBelow = const Nothing + +instance DiscreteOrdered Float where + adjacent _ _ = False + adjacentBelow = const Nothing + +instance (Integral a) => DiscreteOrdered (Ratio a) where + adjacent _ _ = False + adjacentBelow = const Nothing + +instance Ord a => DiscreteOrdered [a] where + adjacent _ _ = False + adjacentBelow = const Nothing + +instance (Ord a, DiscreteOrdered b) => DiscreteOrdered (a, b) + where + adjacent (x1, x2) (y1, y2) = (x1 == y1) && adjacent x2 y2 + adjacentBelow (x1, x2) = do -- Maybe monad + x2' <- adjacentBelow x2 + return (x1, x2') + +instance (Ord a, Ord b, DiscreteOrdered c) => DiscreteOrdered (a, b, c) + where + adjacent (x1, x2, x3) (y1, y2, y3) = + (x1 == y1) && (x2 == y2) && adjacent x3 y3 + adjacentBelow (x1, x2, x3) = do -- Maybe monad + x3' <- adjacentBelow x3 + return (x1, x2, x3') + +instance (Ord a, Ord b, Ord c, DiscreteOrdered d) => + DiscreteOrdered (a, b, c, d) + where + adjacent (x1, x2, x3, x4) (y1, y2, y3, y4) = + (x1 == y1) && (x2 == y2) && (x3 == y3) && adjacent x4 y4 + adjacentBelow (x1, x2, x3, x4) = do -- Maybe monad + x4' <- adjacentBelow x4 + return (x1, x2, x3, x4') + + +-- | Check adjacency for sparse enumerated types (i.e. where there +-- is no value between @x@ and @succ x@). +enumAdjacent :: (Ord a, Enum a) => a -> a -> Bool +enumAdjacent x y = (succ x == y) + +-- | Check adjacency, allowing for case where x = maxBound. Use as the +-- definition of "adjacent" for bounded enumerated types such as Int and Char. +boundedAdjacent :: (Ord a, Enum a) => a -> a -> Bool +boundedAdjacent x y = if x < y then succ x == y else False + + +-- | The usual implementation of 'adjacentBelow' for bounded enumerated types. +boundedBelow :: (Eq a, Enum a, Bounded a) => a -> Maybe a +boundedBelow x = if x == minBound then Nothing else Just $ pred x + +{- | +A Boundary is a division of an ordered type into values above +and below the boundary. No value can sit on a boundary. + +Known bug: for Bounded types + +* @BoundaryAbove maxBound < BoundaryAboveAll@ + +* @BoundaryBelow minBound > BoundaryBelowAll@ + +This is incorrect because there are no possible values in +between the left and right sides of these inequalities. +-} + +data Boundary a = + -- | The argument is the highest value below the boundary. + BoundaryAbove a | + -- | The argument is the lowest value above the boundary. + BoundaryBelow a | + -- | The boundary above all values. + BoundaryAboveAll | + -- | The boundary below all values. + BoundaryBelowAll + deriving (Show) + +-- | True if the value is above the boundary, false otherwise. +above :: Ord v => Boundary v -> v -> Bool +above (BoundaryAbove b) v = v > b +above (BoundaryBelow b) v = v >= b +above BoundaryAboveAll _ = False +above BoundaryBelowAll _ = True + +-- | Same as 'above', but with the arguments reversed for more intuitive infix +-- usage. +(/>/) :: Ord v => v -> Boundary v -> Bool +(/>/) = flip above + +instance (DiscreteOrdered a) => Eq (Boundary a) where + b1 == b2 = compare b1 b2 == EQ + +instance (DiscreteOrdered a) => Ord (Boundary a) where + -- Comparison alogrithm based on brute force and ignorance: + -- enumerate all combinations. + + compare boundary1 boundary2 = + case boundary1 of + BoundaryAbove b1 -> + case boundary2 of + BoundaryAbove b2 -> compare b1 b2 + BoundaryBelow b2 -> + if b1 < b2 + then + if adjacent b1 b2 then EQ else LT + else GT + BoundaryAboveAll -> LT + BoundaryBelowAll -> GT + BoundaryBelow b1 -> + case boundary2 of + BoundaryAbove b2 -> + if b1 > b2 + then + if adjacent b2 b1 then EQ else GT + else LT + BoundaryBelow b2 -> compare b1 b2 + BoundaryAboveAll -> LT + BoundaryBelowAll -> GT + BoundaryAboveAll -> + case boundary2 of + BoundaryAboveAll -> EQ + _ -> GT + BoundaryBelowAll -> + case boundary2 of + BoundaryBelowAll -> EQ + _ -> LT + +-- QuickCheck Generator + +instance Arbitrary a => Arbitrary (Boundary a) where + arbitrary = frequency [ + (1, return BoundaryAboveAll), + (1, return BoundaryBelowAll), + (18, do + v <- arbitrary + oneof [return $ BoundaryAbove v, return $ BoundaryBelow v] + )] + +instance CoArbitrary a => CoArbitrary (Boundary a) where + coarbitrary BoundaryBelowAll = variant (0 :: Int) + coarbitrary BoundaryAboveAll = variant (1 :: Int) + coarbitrary (BoundaryBelow v) = variant (2 :: Int) . coarbitrary v + coarbitrary (BoundaryAbove v) = variant (3 :: Int) . coarbitrary v + diff --git a/src/Data/Ranged/RangedSet.hs b/src/Data/Ranged/RangedSet.hs new file mode 100644 index 0000000..422e57f --- /dev/null +++ b/src/Data/Ranged/RangedSet.hs @@ -0,0 +1,486 @@ +module Data.Ranged.RangedSet ( + -- ** Ranged Set Type + RSet, + rSetRanges, + -- ** Ranged Set construction functions and their preconditions + makeRangedSet, + unsafeRangedSet, + validRangeList, + normaliseRangeList, + rSingleton, + rSetUnfold, + -- ** Predicates + rSetIsEmpty, + rSetIsFull, + (-?-), rSetHas, + (-<=-), rSetIsSubset, + (-<-), rSetIsSubsetStrict, + -- ** Set Operations + (-\/-), rSetUnion, + (-/\-), rSetIntersection, + (-!-), rSetDifference, + rSetNegation, + -- ** Useful Sets + rSetEmpty, + rSetFull, + -- ** QuickCheck Properties + -- *** Construction + prop_validNormalised, + prop_has, + prop_unfold, + -- *** Basic Operations + prop_union, + prop_intersection, + prop_difference, + prop_negation, + prop_not_empty, + -- *** Some Identities and Inequalities + -- $ConstructionProperties + -- $BasicOperationProperties + -- $SomeIdentitiesAndInequalities + prop_empty, + prop_full, + prop_empty_intersection, + prop_full_union, + prop_union_superset, + prop_intersection_subset, + prop_diff_intersect, + prop_subset, + prop_strict_subset, + prop_union_strict_superset, + prop_intersection_commutes, + prop_union_commutes, + prop_intersection_associates, + prop_union_associates, + prop_de_morgan_intersection, + prop_de_morgan_union, +) where + +import Data.Ranged.Boundaries +import Data.Ranged.Ranges +import Data.Monoid + +import Data.List +import Test.QuickCheck + +infixl 7 -/\- +infixl 6 -\/-, -!- +infixl 5 -<=-, -<-, -?- + +-- | An RSet (for Ranged Set) is a list of ranges. The ranges must be sorted +-- and not overlap. +newtype DiscreteOrdered v => RSet v = RSet {rSetRanges :: [Range v]} + deriving (Eq, Show, Ord) + +instance DiscreteOrdered a => Monoid (RSet a) where + mappend = rSetUnion + mempty = rSetEmpty + +-- | Determine if the ranges in the list are both in order and non-overlapping. +-- If so then they are suitable input for the unsafeRangedSet function. +validRangeList :: DiscreteOrdered v => [Range v] -> Bool + +validRangeList [] = True +validRangeList [Range lower upper] = lower <= upper +validRangeList rs = and $ zipWith okAdjacent rs (tail rs) + where + okAdjacent (Range lower1 upper1) (Range lower2 upper2) = + lower1 <= upper1 && upper1 <= lower2 && lower2 <= upper2 + + +-- | Rearrange and merge the ranges in the list so that they are in order and +-- non-overlapping. +normaliseRangeList :: DiscreteOrdered v => [Range v] -> [Range v] +normaliseRangeList = normalise . sort . filter (not . rangeIsEmpty) + + +-- Private routine: normalise a range list that is known to be already sorted. +-- This precondition is not checked. +normalise :: DiscreteOrdered v => [Range v] -> [Range v] +normalise (r1:r2:rs) = + if overlap r1 r2 + then normalise $ + Range (rangeLower r1) + (max (rangeUpper r1) (rangeUpper r2)) + : rs + else r1 : (normalise $ r2 : rs) + where + overlap (Range _ upper1) (Range lower2 _) = upper1 >= lower2 + +normalise rs = rs + + +-- | Create a new Ranged Set from a list of ranges. The list may contain +-- ranges that overlap or are not in ascending order. +makeRangedSet :: DiscreteOrdered v => [Range v] -> RSet v +makeRangedSet = RSet . normaliseRangeList + + +-- | Create a new Ranged Set from a list of ranges. @validRangeList ranges@ +-- must return @True@. This precondition is not checked. +unsafeRangedSet :: DiscreteOrdered v => [Range v] -> RSet v +unsafeRangedSet = RSet + +-- | Create a Ranged Set from a single element. +rSingleton :: DiscreteOrdered v => v -> RSet v +rSingleton v = unsafeRangedSet [singletonRange v] + +-- | True if the set has no members. +rSetIsEmpty :: DiscreteOrdered v => RSet v -> Bool +rSetIsEmpty = null . rSetRanges + + +-- | True if the negation of the set has no members. +rSetIsFull :: DiscreteOrdered v => RSet v -> Bool +rSetIsFull = rSetIsEmpty . rSetNegation + + +-- | True if the value is within the ranged set. Infix precedence is left 5. +rSetHas, (-?-) :: DiscreteOrdered v => RSet v -> v -> Bool +rSetHas (RSet ls) value = rSetHas1 ls + where + rSetHas1 [] = False + rSetHas1 (r:rs) + | value />/ rangeLower r = rangeHas r value || rSetHas1 rs + | otherwise = False + +(-?-) = rSetHas + +-- | True if the first argument is a subset of the second argument, or is +-- equal. +-- +-- Infix precedence is left 5. +rSetIsSubset, (-<=-) :: DiscreteOrdered v => RSet v -> RSet v -> Bool +rSetIsSubset rs1 rs2 = rSetIsEmpty (rs1 -!- rs2) +(-<=-) = rSetIsSubset + + +-- | True if the first argument is a strict subset of the second argument. +-- +-- Infix precedence is left 5. +rSetIsSubsetStrict, (-<-) :: DiscreteOrdered v => RSet v -> RSet v -> Bool +rSetIsSubsetStrict rs1 rs2 = + rSetIsEmpty (rs1 -!- rs2) + && not (rSetIsEmpty (rs2 -!- rs1)) + +(-<-) = rSetIsSubsetStrict + +-- | Set union for ranged sets. Infix precedence is left 6. +rSetUnion, (-\/-) :: DiscreteOrdered v => RSet v -> RSet v -> RSet v +-- Implementation note: rSetUnion merges the two lists into a single +-- sorted list and then calls normalise to combine overlapping ranges. +rSetUnion (RSet ls1) (RSet ls2) = RSet $ normalise $ merge ls1 ls2 + where + merge ms1 [] = ms1 + merge [] ms2 = ms2 + merge ms1@(h1:t1) ms2@(h2:t2) = + if h1 < h2 + then h1 : merge t1 ms2 + else h2 : merge ms1 t2 + +(-\/-) = rSetUnion + +-- | Set intersection for ranged sets. Infix precedence is left 7. +rSetIntersection, (-/\-) :: DiscreteOrdered v => RSet v -> RSet v -> RSet v +rSetIntersection (RSet ls1) (RSet ls2) = + RSet $ filter (not . rangeIsEmpty) $ merge ls1 ls2 + where + merge ms1@(h1:t1) ms2@(h2:t2) = + rangeIntersection h1 h2 + : if rangeUpper h1 < rangeUpper h2 + then merge t1 ms2 + else merge ms1 t2 + merge _ _ = [] + +(-/\-) = rSetIntersection + + +-- | Set difference. Infix precedence is left 6. +rSetDifference, (-!-) :: DiscreteOrdered v => RSet v -> RSet v -> RSet v +rSetDifference rs1 rs2 = rs1 -/\- (rSetNegation rs2) +(-!-) = rSetDifference + + +-- | Set negation. +rSetNegation :: DiscreteOrdered a => RSet a -> RSet a +rSetNegation set = RSet $ ranges1 $ setBounds1 + where + ranges1 (b1:b2:bs) = Range b1 b2 : ranges1 bs + ranges1 [BoundaryAboveAll] = [] + ranges1 [b] = [Range b BoundaryAboveAll] + ranges1 _ = [] + setBounds1 = case setBounds of + (BoundaryBelowAll : bs) -> bs + _ -> BoundaryBelowAll : setBounds + setBounds = bounds $ rSetRanges set + bounds (r:rs) = rangeLower r : rangeUpper r : bounds rs + bounds _ = [] + +-- | The empty set. +rSetEmpty :: DiscreteOrdered a => RSet a +rSetEmpty = RSet [] + +-- | The set that contains everything. +rSetFull :: DiscreteOrdered a => RSet a +rSetFull = RSet [Range BoundaryBelowAll BoundaryAboveAll] + +-- | Construct a range set. +rSetUnfold :: DiscreteOrdered a => + Boundary a + -- ^ A first lower boundary. + -> (Boundary a -> Boundary a) + -- ^ A function from a lower boundary to an upper boundary, which must + -- return a result greater than the argument (not checked). + -> (Boundary a -> Maybe (Boundary a)) + -- ^ A function from a lower boundary to @Maybe@ the successor lower + -- boundary, which must return a result greater than the argument + -- (not checked). If ranges overlap then they will be merged. + -> RSet a +rSetUnfold bound upperFunc succFunc = RSet $ normalise $ ranges1 bound + where + ranges1 b = + Range b (upperFunc b) + : case succFunc b of + Just b2 -> ranges1 b2 + Nothing -> [] + + +-- QuickCheck Generators + +instance (Arbitrary v, DiscreteOrdered v, Show v) => + Arbitrary (RSet v) + where + arbitrary = frequency [ + (1, return rSetEmpty), + (1, return rSetFull), + (18, do + ls <- arbitrary + return $ makeRangedSet $ rangeList $ sort ls + )] + where + -- Arbitrary lists of ranges don't give many interesting sets after + -- normalisation. So instead generate a sorted list of boundaries + -- and pair them off. Odd boundaries are dropped. + rangeList (b1:b2:bs) = Range b1 b2 : rangeList bs + rangeList _ = [] + +instance (CoArbitrary v, DiscreteOrdered v, Show v) => + CoArbitrary (RSet v) + where + coarbitrary (RSet ls) = variant (0 :: Int) . coarbitrary ls + +-- ================================================================== +-- QuickCheck Properties +-- ================================================================== + +--------------------------------------------------------------------- +-- Construction properties +--------------------------------------------------------------------- + +-- | A normalised range list is valid for unsafeRangedSet +-- +-- > prop_validNormalised ls = validRangeList $ normaliseRangeList ls +prop_validNormalised :: (DiscreteOrdered a) => [Range a] -> Bool +prop_validNormalised ls = validRangeList $ normaliseRangeList ls + + +-- | Iff a value is in a range list then it is in a ranged set +-- constructed from that list. +-- +-- > prop_has ls v = (ls `rangeListHas` v) == makeRangedSet ls -?- v +prop_has :: (DiscreteOrdered a) => [Range a] -> a -> Bool +prop_has ls v = (ls `rangeListHas` v) == makeRangedSet ls -?- v + + +-- | Verifies the correct membership of a set containing all integers +-- starting with the digit \"1\" up to 19999. +-- +-- > prop_unfold = (v <= 99999 && head (show v) == '1') == (initial1 -?- v) +-- > where +-- > initial1 = rSetUnfold (BoundaryBelow 1) addNines times10 +-- > addNines (BoundaryBelow n) = BoundaryAbove $ n * 2 - 1 +-- > times10 (BoundaryBelow n) = +-- > if n <= 1000 then Just $ BoundaryBelow $ n * 10 else Nothing + +prop_unfold :: Integer -> Bool +prop_unfold v = (v <= 99999 && head (show v) == '1') == (initial1 -?- v) + where + initial1 = rSetUnfold (BoundaryBelow 1) addNines times10 + addNines (BoundaryBelow n) = BoundaryAbove $ n * 2 - 1 + addNines _ = error "Can't happen" + times10 (BoundaryBelow n) = + if n <= 10000 then Just $ BoundaryBelow $ n * 10 else Nothing + times10 _ = error "Can't happen" + +--------------------------------------------------------------------- +-- Basic operation properties +--------------------------------------------------------------------- + +-- | Iff a value is in either of two ranged sets then it is in the union of +-- those two sets. +-- +-- > prop_union rs1 rs2 v = +-- > (rs1 -?- v || rs2 -?- v) == ((rs1 -\/- rs2) -?- v) +prop_union :: (DiscreteOrdered a ) => RSet a -> RSet a -> a -> Bool +prop_union rs1 rs2 v = (rs1 -?- v || rs2 -?- v) == ((rs1 -\/- rs2) -?- v) + +-- | Iff a value is in both of two ranged sets then it is n the intersection +-- of those two sets. +-- +-- > prop_intersection rs1 rs2 v = +-- > (rs1 -?- v && rs2 -?- v) == ((rs1 -/\- rs2) -?- v) +prop_intersection :: (DiscreteOrdered a) => RSet a -> RSet a -> a -> Bool +prop_intersection rs1 rs2 v = + (rs1 -?- v && rs2 -?- v) == ((rs1 -/\- rs2) -?- v) + +-- | Iff a value is in ranged set 1 and not in ranged set 2 then it is in the +-- difference of the two. +-- +-- > prop_difference rs1 rs2 v = +-- > (rs1 -?- v && not (rs2 -?- v)) == ((rs1 -!- rs2) -?- v) +prop_difference :: (DiscreteOrdered a) => RSet a -> RSet a -> a -> Bool +prop_difference rs1 rs2 v = + (rs1 -?- v && not (rs2 -?- v)) == ((rs1 -!- rs2) -?- v) + +-- | Iff a value is not in a ranged set then it is in its negation. +-- +-- > prop_negation rs v = rs -?- v == not (rSetNegation rs -?- v) +prop_negation :: (DiscreteOrdered a) => RSet a -> a -> Bool +prop_negation rs v = rs -?- v == not (rSetNegation rs -?- v) + +-- | A set that contains a value is not empty +-- +-- > prop_not_empty rs v = (rs -?- v) ==> not (rSetIsEmpty rs) +prop_not_empty :: (DiscreteOrdered a) => RSet a -> a -> Property +prop_not_empty rs v = (rs -?- v) ==> not (rSetIsEmpty rs) + +--------------------------------------------------------------------- +-- Some identities and inequalities of sets +--------------------------------------------------------------------- + +-- | The empty set has no members. +-- +-- > prop_empty v = not (rSetEmpty -?- v) +prop_empty :: (DiscreteOrdered a) => a -> Bool +prop_empty v = not (rSetEmpty -?- v) + +-- | The full set has every member. +-- +-- > prop_full v = rSetFull -?- v +prop_full :: (DiscreteOrdered a) => a -> Bool +prop_full v = rSetFull -?- v + +-- | The intersection of a set with its negation is empty. +-- +-- > prop_empty_intersection rs = +-- > rSetIsEmpty (rs -/\- rSetNegation rs) +prop_empty_intersection :: (DiscreteOrdered a) => RSet a -> Bool +prop_empty_intersection rs = + rSetIsEmpty (rs -/\- rSetNegation rs) + +-- | The union of a set with its negation is full. +-- +-- > prop_full_union rs v = +-- > rSetIsFull (rs -\/- rSetNegation rs) +prop_full_union :: (DiscreteOrdered a) => RSet a -> Bool +prop_full_union rs = + rSetIsFull (rs -\/- rSetNegation rs) + +-- | The union of two sets is the non-strict superset of both. +-- +-- > prop_union_superset rs1 rs2 = +-- > rs1 -<=- u && rs2 -<=- u +-- > where +-- > u = rs1 -\/- rs2 +prop_union_superset :: (DiscreteOrdered a) => RSet a -> RSet a -> Bool +prop_union_superset rs1 rs2 = + rs1 -<=- u && rs2 -<=- u + where + u = rs1 -\/- rs2 + +-- | The intersection of two sets is the non-strict subset of both. +-- +-- > prop_intersection_subset rs1 rs2 = +-- > i -<=- rs1 && i -<=- rs2 +-- > where +-- > i = rs1 -/\- rs2 +prop_intersection_subset :: (DiscreteOrdered a) => RSet a -> RSet a -> Bool +prop_intersection_subset rs1 rs2 = i -<=- rs1 && i -<=- rs2 + where + i = rs1 -/\- rs2 + +-- | The difference of two sets intersected with the subtractand is empty. +-- +-- > prop_diff_intersect rs1 rs2 = +-- > rSetIsEmpty ((rs1 -!- rs2) -/\- rs2) +prop_diff_intersect :: (DiscreteOrdered a) => RSet a -> RSet a -> Bool +prop_diff_intersect rs1 rs2 = rSetIsEmpty ((rs1 -!- rs2) -/\- rs2) + +-- | A set is the non-strict subset of itself. +-- +-- > prop_subset rs = rs -<=- rs +prop_subset :: (DiscreteOrdered a) => RSet a -> Bool +prop_subset rs = rs -<=- rs + +-- | A set is not the strict subset of itself. +-- +-- > prop_strict_subset rs = not (rs -<- rs) +prop_strict_subset :: (DiscreteOrdered a) => RSet a -> Bool +prop_strict_subset rs = not (rs -<- rs) + +-- | If rs1 - rs2 is not empty then the union of rs1 and rs2 will be a strict +-- superset of rs2. +-- +-- > prop_union_strict_superset rs1 rs2 = +-- > (not $ rSetIsEmpty (rs1 -!- rs2)) +-- > ==> (rs2 -<- (rs1 -\/- rs2)) +prop_union_strict_superset :: (DiscreteOrdered a) => RSet a -> RSet a -> Property +prop_union_strict_superset rs1 rs2 = + (not $ rSetIsEmpty (rs1 -!- rs2)) ==> (rs2 -<- (rs1 -\/- rs2)) + +-- | Intersection commutes. +-- +-- > prop_intersection_commutes rs1 rs2 = (rs1 -/\- rs2) == (rs2 -/\- rs1) +prop_intersection_commutes :: (DiscreteOrdered a) => RSet a -> RSet a -> Bool +prop_intersection_commutes rs1 rs2 = (rs1 -/\- rs2) == (rs2 -/\- rs1) + +-- | Union commutes. +-- +-- > prop_union_commutes rs1 rs2 = (rs1 -\/- rs2) == (rs2 -\/- rs1) +prop_union_commutes :: (DiscreteOrdered a) => RSet a -> RSet a -> Bool +prop_union_commutes rs1 rs2 = (rs1 -\/- rs2) == (rs2 -\/- rs1) + +-- | Intersection associates. +-- +-- > prop_intersection_associates rs1 rs2 rs3 = +-- > ((rs1 -/\- rs2) -/\- rs3) == (rs1 -/\- (rs2 -/\- rs3)) +prop_intersection_associates :: (DiscreteOrdered a) => + RSet a -> RSet a -> RSet a -> Bool +prop_intersection_associates rs1 rs2 rs3 = + ((rs1 -/\- rs2) -/\- rs3) == (rs1 -/\- (rs2 -/\- rs3)) + +-- | Union associates. +-- +-- > prop_union_associates rs1 rs2 rs3 = +-- > ((rs1 -\/- rs2) -\/- rs3) == (rs1 -\/- (rs2 -\/- rs3)) +prop_union_associates :: (DiscreteOrdered a) => + RSet a -> RSet a -> RSet a -> Bool +prop_union_associates rs1 rs2 rs3 = + ((rs1 -\/- rs2) -\/- rs3) == (rs1 -\/- (rs2 -\/- rs3)) + +-- | De Morgan's Law for Intersection. +-- +-- > prop_de_morgan_intersection rs1 rs2 = +-- > rSetNegation (rs1 -/\- rs2) == (rSetNegation rs1 -\/- rSetNegation rs2) +prop_de_morgan_intersection :: (DiscreteOrdered a) => RSet a -> RSet a -> Bool +prop_de_morgan_intersection rs1 rs2 = + rSetNegation (rs1 -/\- rs2) == (rSetNegation rs1 -\/- rSetNegation rs2) + +-- | De Morgan's Law for Union. +-- +-- > prop_de_morgan_union rs1 rs2 = +-- > rSetNegation (rs1 -\/- rs2) == (rSetNegation rs1 -/\- rSetNegation rs2) + +prop_de_morgan_union :: (DiscreteOrdered a) => RSet a -> RSet a -> Bool +prop_de_morgan_union rs1 rs2 = + rSetNegation (rs1 -\/- rs2) == (rSetNegation rs1 -/\- rSetNegation rs2) diff --git a/src/Data/Ranged/Ranges.hs b/src/Data/Ranged/Ranges.hs new file mode 100644 index 0000000..5ff8c05 --- /dev/null +++ b/src/Data/Ranged/Ranges.hs @@ -0,0 +1,360 @@ +----------------------------------------------------------------------------- +-- +-- Module : Data.Ranged.Ranges +-- Copyright : (c) Paul Johnson 2006 +-- License : BSD-style +-- Maintainer : paul@cogito.org.uk +-- Stability : experimental +-- Portability : portable +-- +----------------------------------------------------------------------------- + +-- | A range has an upper and lower boundary. +module Data.Ranged.Ranges ( + -- ** Construction + Range (..), + emptyRange, + fullRange, + -- ** Predicates + rangeIsEmpty, + rangeIsFull, + rangeOverlap, + rangeEncloses, + rangeSingletonValue, + -- ** Membership + rangeHas, + rangeListHas, + -- ** Set Operations + singletonRange, + rangeIntersection, + rangeUnion, + rangeDifference, + -- ** QuickCheck properties + prop_unionRange, + prop_unionRangeLength, + prop_intersectionRange, + prop_differenceRange, + prop_intersectionOverlap, + prop_enclosureUnion, + prop_singletonRangeHas, + prop_singletonRangeHasOnly, + prop_singletonRangeConverse, + prop_emptyNonSingleton, + prop_fullNonSingleton, + prop_nonSingleton, + prop_intSingleton +) where + +import Control.Monad +import Data.Ranged.Boundaries +import Data.Maybe +import Test.QuickCheck + +-- | A Range has upper and lower boundaries. +data Ord v => Range v = Range {rangeLower, rangeUpper :: Boundary v} + +instance (DiscreteOrdered a) => Eq (Range a) where + r1 == r2 = (rangeIsEmpty r1 && rangeIsEmpty r2) || + (rangeLower r1 == rangeLower r2 && + rangeUpper r1 == rangeUpper r2) + + +instance (DiscreteOrdered a) => Ord (Range a) where + compare r1 r2 + | r1 == r2 = EQ + | rangeIsEmpty r1 = LT + | rangeIsEmpty r2 = GT + | otherwise = compare (rangeLower r1, rangeUpper r1) + (rangeLower r2, rangeUpper r2) + +instance (Show a, DiscreteOrdered a) => Show (Range a) where + show r + | rangeIsEmpty r = "Empty" + | rangeIsFull r = "All x" + | otherwise = + case rangeSingletonValue r of + Just v -> "x == " ++ show v + Nothing -> lowerBound ++ "x" ++ upperBound + where + lowerBound = case rangeLower r of + BoundaryBelowAll -> "" + BoundaryBelow v -> show v ++ " <= " + BoundaryAbove v -> show v ++ " < " + BoundaryAboveAll -> error "show Range: lower bound is BoundaryAboveAll" + upperBound = case rangeUpper r of + BoundaryBelowAll -> error "show Range: upper bound is BoundaryBelowAll" + BoundaryBelow v -> " < " ++ show v + BoundaryAbove v -> " <= " ++ show v + BoundaryAboveAll -> "" + + +-- | True if the value is within the range. +rangeHas :: Ord v => Range v -> v -> Bool + +rangeHas (Range b1 b2) v = + (v />/ b1) && not (v />/ b2) + + +-- | True if the value is within one of the ranges. +rangeListHas :: Ord v => + [Range v] -> v -> Bool +rangeListHas ls v = or $ map (\r -> rangeHas r v) ls + + +-- | The empty range +emptyRange :: DiscreteOrdered v => Range v +emptyRange = Range BoundaryAboveAll BoundaryBelowAll + + +-- | The full range. All values are within it. +fullRange :: DiscreteOrdered v => Range v +fullRange = Range BoundaryBelowAll BoundaryAboveAll + + +-- | A range containing a single value +singletonRange :: DiscreteOrdered v => v -> Range v +singletonRange v = Range (BoundaryBelow v) (BoundaryAbove v) + + +-- | If the range is a singleton, returns @Just@ the value. Otherwise returns +-- @Nothing@. +-- +-- Known bug: This always returns @Nothing@ for ranges including +-- @BoundaryBelowAll@ or @BoundaryAboveAll@. For bounded types this can be +-- incorrect. For instance, the following range only contains one value: +-- +-- > Range (BoundaryBelow maxBound) BoundaryAboveAll +rangeSingletonValue :: DiscreteOrdered v => Range v -> Maybe v +rangeSingletonValue (Range (BoundaryBelow v1) (BoundaryBelow v2)) + | adjacent v1 v2 = Just v1 + | otherwise = Nothing +rangeSingletonValue (Range (BoundaryBelow v1) (BoundaryAbove v2)) + | v1 == v2 = Just v1 + | otherwise = Nothing +rangeSingletonValue (Range (BoundaryAbove v1) (BoundaryBelow v2)) = + do + v2' <- adjacentBelow v2 + v2'' <- adjacentBelow v2' + if v1 == v2'' then return v2' else Nothing +rangeSingletonValue (Range (BoundaryAbove v1) (BoundaryAbove v2)) + | adjacent v1 v2 = Just v2 + | otherwise = Nothing +rangeSingletonValue (Range _ _) = Nothing + +-- | A range is empty unless its upper boundary is greater than its lower +-- boundary. +rangeIsEmpty :: DiscreteOrdered v => Range v -> Bool +rangeIsEmpty (Range lower upper) = upper <= lower + + +-- | A range is full if it contains every possible value. +rangeIsFull :: DiscreteOrdered v => Range v -> Bool +rangeIsFull = (== fullRange) + +-- | Two ranges overlap if their intersection is non-empty. +rangeOverlap :: DiscreteOrdered v => Range v -> Range v -> Bool +rangeOverlap r1 r2 = + not (rangeIsEmpty r1) + && not (rangeIsEmpty r2) + && not (rangeUpper r1 <= rangeLower r2 || rangeUpper r2 <= rangeLower r1) + + +-- | The first range encloses the second if every value in the second range is +-- also within the first range. If the second range is empty then this is +-- always true. +rangeEncloses :: DiscreteOrdered v => Range v -> Range v -> Bool +rangeEncloses r1 r2 = + (rangeLower r1 <= rangeLower r2 && rangeUpper r2 <= rangeUpper r1) + || rangeIsEmpty r2 + + +-- | Intersection of two ranges, if any. +rangeIntersection :: DiscreteOrdered v => Range v -> Range v -> Range v +rangeIntersection r1@(Range lower1 upper1) r2@(Range lower2 upper2) + | rangeIsEmpty r1 || rangeIsEmpty r2 = emptyRange + | otherwise = Range (max lower1 lower2) (min upper1 upper2) + + +-- | Union of two ranges. Returns one or two results. +-- +-- If there are two results then they are guaranteed to have a non-empty +-- gap in between, but may not be in ascending order. +rangeUnion :: DiscreteOrdered v => Range v -> Range v -> [Range v] +rangeUnion r1@(Range lower1 upper1) r2@(Range lower2 upper2) + | rangeIsEmpty r1 = [r2] + | rangeIsEmpty r2 = [r1] + | otherwise = + if touching then [Range lower upper] else [r1, r2] + where + touching = (max lower1 lower2) <= (min upper1 upper2) + lower = min lower1 lower2 + upper = max upper1 upper2 + + +-- | @range1@ minus @range2@. Returns zero, one or two results. Multiple +-- results are guaranteed to have non-empty gaps in between, but may not be in +-- ascending order. +rangeDifference :: DiscreteOrdered v => Range v -> Range v -> [Range v] + +rangeDifference r1@(Range lower1 upper1) (Range lower2 upper2) = + -- There are six possibilities + -- 1: r2 completely less than r1 + -- 2: r2 overlaps bottom of r1 + -- 3: r2 encloses r1 + -- 4: r1 encloses r2 + -- 5: r2 overlaps top of r1 + -- 6: r2 completely greater than r1 + if intersects + then -- Cases 2,3,4,5 + filter (not . rangeIsEmpty) [Range lower1 lower2, Range upper2 upper1] + else -- Cases 1, 6 + [r1] + where + intersects = (max lower1 lower2) < (min upper1 upper2) + + +-- QuickCheck generators + +instance (Arbitrary v, DiscreteOrdered v, Show v) => + Arbitrary (Range v) where + + arbitrary = frequency [ + (17, do -- Ordinary range + b1 <- arbitrary + b2 <- arbitrary + if b1 < b2 + then return $ Range b1 b2 + else return $ Range b2 b1 + ), + (1, do -- Singleton range + v <- arbitrary + return $ singletonRange v + ), + (1, return emptyRange), + (1, return fullRange) + ] + +instance (CoArbitrary v, DiscreteOrdered v, Show v) => + CoArbitrary (Range v) where + + coarbitrary (Range lower upper) = + variant (0 :: Int) . coarbitrary lower . coarbitrary upper + + + +-- QuickCheck Properties + +-- | The union of two ranges has a value iff either range has it. +-- +-- > prop_unionRange r1 r2 n = +-- > (r1 `rangeHas` n || r2 `rangeHas` n) +-- > == (r1 `rangeUnion` r2) `rangeListHas` n +prop_unionRange :: (DiscreteOrdered a) => Range a -> Range a -> a -> Bool +prop_unionRange r1 r2 n = + (r1 `rangeHas` n || r2 `rangeHas` n) + == (r1 `rangeUnion` r2) `rangeListHas` n + +-- | The union of two ranges always contains one or two ranges. +-- +-- > prop_unionRangeLength r1 r2 = (n == 1) || (n == 2) +-- > where n = length $ rangeUnion r1 r2 +prop_unionRangeLength :: (DiscreteOrdered a) => Range a -> Range a -> Bool +prop_unionRangeLength r1 r2 = (n == 1) || (n == 2) + where n = length $ rangeUnion r1 r2 + +-- | The intersection of two ranges has a value iff both ranges have it. +-- +-- > prop_intersectionRange r1 r2 n = +-- > (r1 `rangeHas` n && r2 `rangeHas` n) +-- > == (r1 `rangeIntersection` r2) `rangeHas` n +prop_intersectionRange :: (DiscreteOrdered a) => Range a -> Range a -> a -> Bool +prop_intersectionRange r1 r2 n = + (r1 `rangeHas` n && r2 `rangeHas` n) + == (r1 `rangeIntersection` r2) `rangeHas` n + +-- | The difference of two ranges has a value iff the first range has it and +-- the second does not. +-- +-- > prop_differenceRange r1 r2 n = +-- > (r1 `rangeHas` n && not (r2 `rangeHas` n)) +-- > == (r1 `rangeDifference` r2) `rangeListHas` n +prop_differenceRange :: (DiscreteOrdered a) => Range a -> Range a -> a -> Bool +prop_differenceRange r1 r2 n = + (r1 `rangeHas` n && not (r2 `rangeHas` n)) + == (r1 `rangeDifference` r2) `rangeListHas` n + +-- | Iff two ranges overlap then their intersection is non-empty. +-- +-- > prop_intersectionOverlap r1 r2 = +-- > (rangeIsEmpty $ rangeIntersection r1 r2) == (rangeOverlap r1 r2) +prop_intersectionOverlap :: (DiscreteOrdered a) => Range a -> Range a -> Bool +prop_intersectionOverlap r1 r2 = + (rangeIsEmpty $ rangeIntersection r1 r2) == not (rangeOverlap r1 r2) + +-- | Range enclosure makes union an identity function. +-- +-- > prop_enclosureUnion r1 r2 = +-- > rangeEncloses r1 r2 == (rangeUnion r1 r2 == [r1]) +prop_enclosureUnion :: (DiscreteOrdered a) => Range a -> Range a -> Bool +prop_enclosureUnion r1 r2 = rangeEncloses r1 r2 == (rangeUnion r1 r2 == [r1]) + +-- | Range Singleton has its member. +-- +-- > prop_singletonRangeHas v = singletonRange v `rangeHas` v +prop_singletonRangeHas :: (DiscreteOrdered a) => a -> Bool +prop_singletonRangeHas v = singletonRange v `rangeHas` v + +-- | Range Singleton has only its member. +-- +-- > prop_singletonHasOnly v1 v2 = +-- > (v1 == v2) == (singletonRange v1 `rangeHas` v2) +prop_singletonRangeHasOnly :: (DiscreteOrdered a) => a -> a -> Bool +prop_singletonRangeHasOnly v1 v2 = + (v1 == v2) == (singletonRange v1 `rangeHas` v2) + +-- | A singleton range can have its value extracted. +-- +-- > prop_singletonRangeConverse v = +-- > rangeSingletonValue (singletonRange v) == Just v +prop_singletonRangeConverse:: (DiscreteOrdered a) => a -> Bool +prop_singletonRangeConverse v = + rangeSingletonValue (singletonRange v) == Just v + +-- | The empty range is not a singleton. +-- +-- > prop_emptyNonSingleton = rangeSingletonValue emptyRange == Nothing +prop_emptyNonSingleton :: Bool +prop_emptyNonSingleton = + rangeSingletonValue (emptyRange :: Range Int) == Nothing + +-- | The full range is not a singleton. +-- +-- > prop_fullNonSingleton = rangeSingletonValue fullRange == Nothing +prop_fullNonSingleton :: Bool +prop_fullNonSingleton = + rangeSingletonValue (fullRange :: Range Int) == Nothing + +-- | For real x and y, @x < y@ implies that any range between them is a +-- non-singleton. +prop_nonSingleton :: Double -> Double -> Property +prop_nonSingleton x y = (x < y) ==> null $ mapMaybe rangeSingletonValue rs + where rs = [ + Range (BoundaryBelow x) (BoundaryBelow y), + Range (BoundaryAbove x) (BoundaryBelow y), + Range (BoundaryBelow x) (BoundaryAbove y), + Range (BoundaryAbove x) (BoundaryAbove y)] + + +-- | For all integers x and y, any range formed from boundaries on either side +-- of x and y is a singleton iff it contains exactly one integer. +prop_intSingleton :: Integer -> Integer -> Property +prop_intSingleton x y = forAll (rangeAround x y) $ \r -> + case filter (rangeHas r) [x-1 .. y+1] of + [v] -> rangeSingletonValue r == Just v + _ -> rangeSingletonValue r == Nothing + where + rangeAround v1 v2 = return Range `ap` genBound v1 `ap` genBound v2 + genBound v = elements [BoundaryAbove v, BoundaryBelow v] + + + diff --git a/src/Info.hs b/src/Info.hs index b81ef73..b236017 100644 --- a/src/Info.hs +++ b/src/Info.hs @@ -12,8 +12,8 @@ module Info (infoDFA) where import AbsSyn import qualified Map +import qualified Data.IntMap as IntMap import Util -import CharSet import Data.Array @@ -39,7 +39,7 @@ infoDFA _ func_nm dfa infoArr out = char '\t' . interleave_shows (str "\n\t") - (map infoTransition (Map.toAscList out)) + (map infoTransition (IntMap.toAscList out)) infoAccept (Acc p act lctx rctx) = str "\tAccept" . paren (shows p) . space @@ -58,7 +58,7 @@ infoDFA _ func_nm dfa outputLCtx Nothing = id outputLCtx (Just set) - = paren (outputArr (charSetToArray set)) . char '^' + = paren (show set ++) . char '^' outputArr arr = str "Array.array " . shows (bounds arr) . space diff --git a/src/Main.hs b/src/Main.hs index b52c297..8090356 100644 --- a/src/Main.hs +++ b/src/Main.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE CPP #-} -- ----------------------------------------------------------------------------- -- -- Main.hs, part of Alex @@ -11,6 +12,8 @@ module Main (main) where import AbsSyn import CharSet import DFA +import DFAMin +import NFA import Info import Map ( Map ) import qualified Map hiding ( Map ) @@ -37,6 +40,7 @@ import System.Directory ( removeFile ) import System.Environment ( getProgName, getArgs ) import System.Exit ( ExitCode(..), exitWith ) import System.IO ( stderr, Handle, IOMode(..), openFile, hClose, hPutStr, hPutStrLn ) +import System.IO ( hSetBuffering, BufferMode(..) ) #if __GLASGOW_HASKELL__ >= 612 import System.IO ( hGetContents, hSetEncoding, utf8 ) #endif @@ -132,6 +136,10 @@ alex cli file basename script = do | OptGhcTarget `elem` cli = GhcTarget | otherwise = HaskellTarget + let encoding + | OptLatin1 `elem` cli = Latin1 + | otherwise = UTF8 + template_dir <- templateDir getDataDir cli let template_name = templateFile template_dir target cli @@ -158,11 +166,22 @@ alex cli file basename script = do do str <- alexReadFile (fromJust wrapper_name) hPutStr out_h str - let dfa = scanner2dfa scanner_final scs + let dfa = scanner2dfa encoding scanner_final scs + min_dfa = minimizeDFA dfa nm = scannerName scanner_final + + put_info "\nStart codes\n" + put_info (show $ scs) + put_info "\nScanner\n" + put_info (show $ scanner_final) + put_info "\nNFA\n" + put_info (show $ scanner2nfa encoding scanner_final scs) + put_info "\nDFA" put_info (infoDFA 1 nm dfa "") - hPutStr out_h (outputDFA target 1 nm dfa "") + put_info "\nMinimized DFA" + put_info (infoDFA 1 nm min_dfa "") + hPutStr out_h (outputDFA target 1 nm min_dfa "") injectCode maybe_footer file out_h @@ -268,8 +287,9 @@ infoStart x_file info_file = do infoHeader :: Handle -> FilePath -> IO () infoHeader h file = do +-- hSetBuffering h NoBuffering hPutStrLn h ("Info file produced by Alex version " ++ projectVersion ++ - ", from " ++ file) + ", from " ++ file) hPutStrLn h hline hPutStr h "\n" @@ -278,7 +298,7 @@ initialParserEnv = (initSetEnv, initREEnv) initSetEnv :: Map String CharSet initSetEnv = Map.fromList [("white", charSet " \t\n\v\f\r"), - ("printable", charSet [chr 32 .. chr 126]), + ("printable", charSetRange (chr 32) (chr 0x10FFFF)), -- FIXME: Look it up the unicode standard (".", charSetComplement emptyCharSet `charSetMinus` charSetSingleton '\n')] @@ -294,6 +314,7 @@ data CLIFlags | OptOutputFile FilePath | OptInfoFile (Maybe FilePath) | OptTemplateDir FilePath + | OptLatin1 | DumpHelp | DumpVersion deriving Eq @@ -308,6 +329,8 @@ argInfo = [ "look in DIR for template files", Option ['g'] ["ghc"] (NoArg OptGhcTarget) "use GHC extensions", + Option ['l'] ["latin1"] (NoArg OptLatin1) + "generated lexer will use the Latin-1 encoding instead of UTF-8", Option ['d'] ["debug"] (NoArg OptDebugParser) "produce a debugging scanner", Option ['?'] ["help"] (NoArg DumpHelp) diff --git a/src/Map.hs b/src/Map.hs index 321d8fd..8e95749 100644 --- a/src/Map.hs +++ b/src/Map.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE CPP #-} module Map ( Map, member, lookup, findWithDefault, diff --git a/src/NFA.hs b/src/NFA.hs index 6556c69..8f9270b 100644 --- a/src/NFA.hs +++ b/src/NFA.hs @@ -17,15 +17,14 @@ module NFA where import AbsSyn -import CharSet ( CharSet, charSetToArray ) +import CharSet import DFS ( t_close, out ) import Map ( Map ) import qualified Map hiding ( Map ) import Util ( str, space ) -import Control.Monad ( zipWithM, zipWithM_ ) +import Control.Monad ( forM_, zipWithM, zipWithM_, when ) import Data.Array ( Array, (!), array, listArray, assocs, bounds ) ---import Debug.Trace -- Each state of a nondeterministic automaton contains a list of `Accept' -- values, a list of epsilon transitions (an epsilon transition represents a @@ -42,14 +41,14 @@ type NFA = Array SNum NState data NState = NSt { nst_accs :: [Accept Code], nst_cl :: [SNum], - nst_outs :: [(CharSet,SNum)] + nst_outs :: [(ByteSet,SNum)] } -- Debug stuff instance Show NState where showsPrec _ (NSt accs cl outs) = str "NSt " . shows accs . space . shows cl . space . - shows [ (charSetToArray c, s) | (c,s) <- outs ] + shows [ (c, s) | (c,s) <- outs ] {- From the Scan Module @@ -75,9 +74,9 @@ instance Show NState where -- as that startcode, and epsilon transitions from this state to each -- of the sub-NFAs for each of the tokens acceptable in that startcode. -scanner2nfa:: Scanner -> [StartCode] -> NFA -scanner2nfa Scanner{scannerTokens = toks} startcodes - = runNFA $ +scanner2nfa:: Encoding -> Scanner -> [StartCode] -> NFA +scanner2nfa enc Scanner{scannerTokens = toks} startcodes + = runNFA enc $ do -- make a start state for each start code (these will be -- numbered from zero). @@ -109,7 +108,11 @@ scanner2nfa Scanner{scannerTokens = toks} startcodes accept r_e rctxt_accept return (RightContextRExp r_b) - accept e (Acc prio code lctx rctx_e) + let lctx' = case lctx of + Nothing -> Nothing + Just st -> Just st + + accept e (Acc prio code lctx' rctx_e) return b tok_transitions toks_with_states start_code start_state = do @@ -157,17 +160,17 @@ rexp2nfa b e (Ques re) = do type MapNFA = Map SNum NState -newtype NFAM a = N {unN :: SNum -> MapNFA -> (SNum, MapNFA, a)} +newtype NFAM a = N {unN :: SNum -> MapNFA -> Encoding -> (SNum, MapNFA, a)} instance Monad NFAM where - return a = N $ \s n -> (s,n,a) + return a = N $ \s n e -> (s,n,a) - m >>= k = N $ \s n -> case unN m s n of - (s', n', a) -> unN (k a) s' n' + m >>= k = N $ \s n e -> case unN m s n e of + (s', n', a) -> unN (k a) s' n' e -runNFA :: NFAM () -> NFA -runNFA m = case unN m 0 Map.empty of - (s, nfa_map, ()) -> -- trace (show (Map.toAscList nfa_map)) $ +runNFA :: Encoding -> NFAM () -> NFA +runNFA e m = case unN m 0 Map.empty e of + (s, nfa_map, ()) -> -- trace ("runNfa.." ++ show (Map.toAscList nfa_map)) $ e_close (array (0,s-1) (Map.toAscList nfa_map)) e_close:: Array Int NState -> NFA @@ -178,10 +181,51 @@ e_close ar = listArray bds bds@(_,hi) = bounds ar newState :: NFAM SNum -newState = N $ \s n -> (s+1,n,s) +newState = N $ \s n e -> (s+1,n,s) + +getEncoding :: NFAM Encoding +getEncoding = N $ \s n e -> (s,n,e) + +anyBytes :: SNum -> Int -> SNum -> NFAM () +anyBytes from 0 to = epsilonEdge from to +anyBytes from n to = do + s <- newState + byteEdge from (byteSetRange 0 0xff) s + anyBytes s (n-1) to + +bytesEdge :: SNum -> [Byte] -> [Byte] -> SNum -> NFAM () +bytesEdge from [] [] to = epsilonEdge from to +bytesEdge from [x] [y] to = byteEdge from (byteSetRange x y) to -- (OPTIMISATION) +bytesEdge from (x:xs) (y:ys) to + | x == y = do + s <- newState + byteEdge from (byteSetSingleton x) s + bytesEdge s xs ys to + | x < y = do + do s <- newState + byteEdge from (byteSetSingleton x) s + bytesEdge s xs (fmap (const 0xff) ys) to + + do t <- newState + byteEdge from (byteSetSingleton y) t + bytesEdge t (fmap (const 0x00) xs) ys to + + when ((x+1) <= (y-1)) $ do + u <- newState + byteEdge from (byteSetRange (x+1) (y-1)) u + anyBytes u (length xs) to charEdge :: SNum -> CharSet -> SNum -> NFAM () -charEdge from charset to = N $ \s n -> (s, addEdge n, ()) +charEdge from charset to = do + -- trace ("charEdge: " ++ (show $ charset) ++ " => " ++ show (byteRanges charset)) $ + e <- getEncoding + forM_ (byteRanges e charset) $ \(xs,ys) -> do + bytesEdge from xs ys to + + + +byteEdge :: SNum -> ByteSet -> SNum -> NFAM () +byteEdge from charset to = N $ \s n e -> (s, addEdge n, ()) where addEdge n = case Map.lookup from n of @@ -193,7 +237,7 @@ charEdge from charset to = N $ \s n -> (s, addEdge n, ()) epsilonEdge :: SNum -> SNum -> NFAM () epsilonEdge from to | from == to = return () - | otherwise = N $ \s n -> (s, addEdge n, ()) + | otherwise = N $ \s n e -> (s, addEdge n, ()) where addEdge n = case Map.lookup from n of @@ -201,7 +245,7 @@ epsilonEdge from to Just (NSt acc eps trans) -> Map.insert from (NSt acc (to:eps) trans) n accept :: SNum -> Accept Code -> NFAM () -accept state new_acc = N $ \s n -> (s, addAccept n, ()) +accept state new_acc = N $ \s n e -> (s, addAccept n, ()) where addAccept n = case Map.lookup state n of diff --git a/src/Output.hs b/src/Output.hs index 97acd91..f72e7ea 100644 --- a/src/Output.hs +++ b/src/Output.hs @@ -14,6 +14,7 @@ import AbsSyn import CharSet import Util import qualified Map +import qualified Data.IntMap as IntMap import Control.Monad.ST ( ST, runST ) import Data.Array ( Array ) @@ -22,7 +23,6 @@ import Data.Array.ST ( STUArray, newArray, readArray, writeArray, freeze ) import Data.Array.Unboxed ( UArray, bounds, assocs, elems, (!), array, listArray ) import Data.Bits import Data.Char ( ord, chr ) --- import Debug.Trace import Data.List ( maximumBy, sortBy, groupBy ) -- ----------------------------------------------------------------------------- @@ -49,7 +49,8 @@ outputDFA target _ _ dfa outputCheck = do_array hexChars16 check_nm table_size check outputDefault = do_array hexChars16 deflt_nm n_states deflt - do_array hex_chars nm upper_bound ints = case target of + do_array hex_chars nm upper_bound ints = -- trace ("do_array: " ++ nm) $ + case target of GhcTarget -> str nm . str " :: AlexAddr\n" . str nm . str " = AlexA# \"" @@ -94,12 +95,7 @@ outputDFA target _ _ dfa . str " `alexAndPred` " . outputRCtx rctx - outputLCtx set - = case charSetElems set of - [] -> error "outputLCtx" - [c] -> str "alexPrevCharIs " . shows c - _other -> str "alexPrevCharIsOneOf " - . paren (outputArr (charSetToArray set)) + outputLCtx set = str "alexPrevCharMatches" . str (charSetQuote set) outputRCtx NoRightContext = id outputRCtx (RightContextRExp sn) @@ -149,8 +145,9 @@ mkTables :: DFA SNum Code [Int], -- default [[Accept Code]] -- accept ) -mkTables dfa - = ( elems base_offs, +mkTables dfa = -- trace (show (defaults)) $ + -- trace (show (fmap (length . snd) dfa_no_defaults)) $ + ( elems base_offs, take max_off (elems table), take max_off (elems check), elems defaults, @@ -171,8 +168,8 @@ mkTables dfa [ expand (dfa_arr!state) | state <- [0..top_state] ] expand (State _ out) = - [(i, lookup' out i) | i <- ['\0'..'\255']] - where lookup' out' i = case Map.lookup i out' of + [(i, lookup' out i) | i <- [0..0xff]] + where lookup' out' i = case IntMap.lookup i out' of Nothing -> -1 Just s -> s @@ -181,7 +178,7 @@ mkTables dfa -- find the most common destination state in a given state, and -- make it the default. - best_default :: [(Char,SNum)] -> SNum + best_default :: [(Int,SNum)] -> SNum best_default prod_list | null sorted = -1 | otherwise = snd (head (maximumBy lengths eq)) @@ -191,13 +188,13 @@ mkTables dfa lengths a b = length a `compare` length b -- remove all the default productions from the DFA - dfa_no_defaults = + dfa_no_defaults = [ (s, prods_without_defaults s out) | (s, out) <- zip [0..] expand_states ] prods_without_defaults s out - = [ (ord c, dest) | (c,dest) <- out, dest /= defaults!s ] + = [ (fromIntegral c, dest) | (c,dest) <- out, dest /= defaults!s ] (base_offs, table, check, max_off) = runST (genTables n_states 255 dfa_no_defaults) diff --git a/src/ParseMonad.hs b/src/ParseMonad.hs index a5957b9..7e71cfd 100644 --- a/src/ParseMonad.hs +++ b/src/ParseMonad.hs @@ -7,7 +7,7 @@ -- ----------------------------------------------------------------------------} module ParseMonad ( - AlexInput, alexInputPrevChar, alexGetChar, + AlexInput, alexInputPrevChar, alexGetChar, alexGetByte, AlexPosn(..), alexStartPos, P, runP, StartCode, failP, lookupSMac, lookupRMac, newSMac, newRMac, @@ -18,21 +18,34 @@ import AbsSyn hiding ( StartCode ) import CharSet ( CharSet ) import Map ( Map ) import qualified Map hiding ( Map ) - +import UTF8 +import Data.Word (Word8) -- ----------------------------------------------------------------------------- -- The input type +--import Codec.Binary.UTF8.Light as UTF8 + +type Byte = Word8 type AlexInput = (AlexPosn, -- current position, Char, -- previous char + [Byte], String) -- current input string alexInputPrevChar :: AlexInput -> Char -alexInputPrevChar (_,c,_) = c +alexInputPrevChar (_,c,_,_) = c + alexGetChar :: AlexInput -> Maybe (Char,AlexInput) -alexGetChar (_,_,[]) = Nothing -alexGetChar (p,_,(c:s)) = let p' = alexMove p c in p' `seq` - Just (c, (p', c, s)) +alexGetChar (_,_,[],[]) = Nothing +alexGetChar (p,_,[],(c:s)) = let p' = alexMove p c in p' `seq` + Just (c, (p', c, [], s)) + +alexGetByte :: AlexInput -> Maybe (Byte,AlexInput) +alexGetByte (p,c,(b:bs),s) = Just (b,(p,c,bs,s)) +alexGetByte (_,_,[],[]) = Nothing +alexGetByte (p,_,[],(c:s)) = let p' = alexMove p c + (b:bs) = UTF8.encode c + in p' `seq` Just (b, (p', c, bs, s)) -- ----------------------------------------------------------------------------- -- Token positions @@ -84,10 +97,10 @@ runP str (senv,renv) (P p) Right (_,a) -> Right a where initial_state = PState{ smac_env=senv, rmac_env=renv, - startcode = 0, input=(alexStartPos,'\n',str) } + startcode = 0, input=(alexStartPos,'\n',[],str) } failP :: String -> P a -failP str = P $ \PState{ input = (p,_,_) } -> Left (Just p,str) +failP str = P $ \PState{ input = (p,_,_,_) } -> Left (Just p,str) -- Macros are expanded during parsing, to simplify the abstract -- syntax. The parsing monad passes around two environments mapping diff --git a/src/Scan.hs b/src/Scan.hs index e0652a3..9f7ea76 100644 --- a/src/Scan.hs +++ b/src/Scan.hs @@ -1,5 +1,8 @@ {-# OPTIONS -fglasgow-exts -cpp #-} -{-# LINE 13 "src/Scan.x" #-} +{-# LINE 13 "Scan.x" #-} + +{-# OPTIONS_GHC -w #-} + module Scan(lexer, AlexPosn(..), Token(..), Tkn(..), tokPosn) where import Data.Char @@ -8,7 +11,7 @@ import ParseMonad #if __GLASGOW_HASKELL__ >= 603 #include "ghcconfig.h" -#else +#elif defined(__GLASGOW_HASKELL__) #include "config.h" #endif #if __GLASGOW_HASKELL__ >= 503 @@ -25,19 +28,20 @@ import GHC.Exts import GlaExts #endif alex_base :: AlexAddr -alex_base = AlexA# "\xf8\xff\xff\xff\x6e\x00\x00\x00\x89\x00\x00\x00\x77\x00\x00\x00\x7c\x00\x00\x00\xfc\xff\xff\xff\xfd\xff\xff\xff\xdb\xff\xff\xff\xdc\xff\xff\xff\x00\x00\x00\x00\x80\x00\x00\x00\x81\x00\x00\x00\x00\x00\x00\x00\x72\x00\x00\x00\xdd\xff\xff\xff\x73\x00\x00\x00\xde\xff\xff\xff\xfb\x00\x00\x00\x6d\x01\x00\x00\x00\x01\x00\x00\x74\x00\x00\x00\x75\x00\x00\x00\xdf\xff\xff\xff\x00\x00\x00\x00\x8a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa7\x01\x00\x00\x00\x00\x00\x00\x96\xff\xff\xff\x9c\xff\xff\xff\xae\xff\xff\xff\xa0\xff\xff\xff\xa1\xff\xff\xff\xad\xff\xff\xff\xa2\xff\xff\xff\xde\x00\x00\x00\x4b\x01\x00\x00\x03\x02\x00\x00\x52\x02\x00\x00\x69\x02\x00\x00\x55\x01\x00\x00\x89\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8f\x02\x00\x00\x02\x03\x00\x00\x74\x03\x00\x00\x84\x02\x00\x00\xc8\x03\x00\x00\x1c\x04\x00\x00\x59\x04\x00\x00\xcb\x04\x00\x00\x3d\x05\x00\x00\xaf\x05\x00\x00\xad\x05\x00\x00\x01\x06\x00\x00\x3e\x06\x00\x00\x00\x00\x00\x00\x87\x00\x00\x00\x8c\x01\x00\x00\xa7\x00\x00\x00\xa8\x00\x00\x00\xe6\xff\xff\xff\x00\x00\x00\x00\xa9\x00\x00\x00\x21\x03\x00\x00\xaa\x00\x00\x00\x19\x01\x00\x00\xe8\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x92\x06\x00\x00\xe6\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x02\x00\x00"# +alex_base = AlexA# "\x01\x00\x00\x00\x77\x00\x00\x00\x92\x00\x00\x00\xf5\xff\xff\xff\xfa\xff\xff\xff\x7b\x00\x00\x00\xe6\x00\x00\x00\x3a\x01\x00\x00\x80\x00\x00\x00\x56\x00\x00\x00\x05\x01\x00\x00\x57\x00\x00\x00\xc3\xff\xff\xff\x77\x01\x00\x00\xb1\x01\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00\x06\x00\x00\x00\xd3\xff\xff\xff\xbe\xff\xff\xff\xc4\xff\xff\xff\xc7\xff\xff\xff\xc8\xff\xff\xff\x7c\x00\x00\x00\x23\x02\x00\x00\x28\x02\x00\x00\x93\x00\x00\x00\xcc\xff\xff\xff\x84\x00\x00\x00\x06\x02\x00\x00\x00\x00\x00\x00\xa0\x00\x00\x00\x2f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7d\x00\x00\x00\x00\x00\x00\x00\x0d\x00\x00\x00\x5d\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa9\x02\x00\x00\xb3\x02\x00\x00\xca\x02\x00\x00\x00\x00\x00\x00\xd2\x02\x00\x00\xda\x02\x00\x00\x12\x00\x00\x00\xe0\x02\x00\x00\x00\x00\x00\x00\x53\x03\x00\x00\xce\x03\x00\x00\x85\x00\x00\x00\x17\x04\x00\x00\xe8\x03\x00\x00\x89\x04\x00\x00\xed\x03\x00\x00\x7e\x00\x00\x00\x00\x00\x00\x00\x90\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xdd\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"# alex_table :: AlexAddr -alex_table = AlexA# "\x00\x00\x04\x00\x04\x00\x04\x00\x04\x00\x04\x00\xff\xff\xff\xff\x05\x00\x05\x00\x0c\x00\x0c\x00\x14\x00\x1e\x00\x1f\x00\x20\x00\x21\x00\x22\x00\x23\x00\x3d\x00\x1c\x00\x43\x00\x00\x00\x00\x00\x04\x00\x2c\x00\x0a\x00\x1a\x00\x1b\x00\x1d\x00\x2c\x00\x2c\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x08\x00\x1a\x00\x1a\x00\x2c\x00\x2c\x00\x2c\x00\x2c\x00\x2c\x00\x2c\x00\x2c\x00\x2c\x00\x2c\x00\x2c\x00\x10\x00\x1a\x00\x46\x00\x2c\x00\x2c\x00\x1a\x00\x2d\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x1a\x00\x26\x00\x1a\x00\x1a\x00\x2c\x00\x2c\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x11\x00\x17\x00\x1a\x00\x1a\x00\x1a\x00\x04\x00\x04\x00\x04\x00\x04\x00\x04\x00\xff\xff\xff\xff\xff\xff\xff\xff\x04\x00\x04\x00\x04\x00\x04\x00\x04\x00\x04\x00\x04\x00\x04\x00\x04\x00\x04\x00\xff\xff\xff\xff\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\xff\xff\x04\x00\x04\x00\x04\x00\x04\x00\x04\x00\x04\x00\x00\x00\x00\x00\x00\x00\x07\x00\x04\x00\x00\x00\x00\x00\x00\x00\x0d\x00\x00\x00\x09\x00\x09\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x4a\x00\x07\x00\x00\x00\x00\x00\x47\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x3b\x00\x00\x00\x00\x00\x4b\x00\x00\x00\x00\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x3b\x00\x3b\x00\x41\x00\x41\x00\x00\x00\x4d\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x48\x00\x13\x00\x13\x00\x13\x00\x13\x00\x13\x00\x13\x00\x13\x00\x13\x00\x13\x00\x13\x00\x24\x00\x24\x00\x24\x00\x24\x00\x24\x00\x24\x00\x24\x00\x24\x00\x24\x00\x24\x00\x00\x00\x00\x00\x00\x00\x13\x00\x00\x00\x00\x00\x00\x00\x00\x00\x13\x00\x00\x00\x12\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x16\x00\x00\x00\x00\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x41\x00\x00\x00\x00\x00\x00\x00\x12\x00\x00\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x13\x00\x13\x00\x13\x00\x13\x00\x13\x00\x24\x00\x24\x00\x24\x00\x24\x00\x24\x00\x24\x00\x24\x00\x24\x00\x24\x00\x24\x00\x29\x00\x29\x00\x29\x00\x29\x00\x29\x00\x29\x00\x29\x00\x29\x00\x13\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x00\x3c\x00\x3c\x00\x3c\x00\x3c\x00\x3c\x00\x16\x00\x00\x00\x00\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3c\x00\x00\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x00\x00\x3a\x00\x00\x00\x00\x00\x12\x00\x00\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x12\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x2e\x00\x33\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x25\x00\x25\x00\x25\x00\x25\x00\x25\x00\x25\x00\x25\x00\x25\x00\x25\x00\x25\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2a\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x28\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x27\x00\x27\x00\x27\x00\x27\x00\x27\x00\x27\x00\x27\x00\x27\x00\x27\x00\x27\x00\x00\x00\x3c\x00\x3c\x00\x3c\x00\x3c\x00\x3c\x00\x00\x00\x27\x00\x27\x00\x27\x00\x27\x00\x27\x00\x27\x00\x27\x00\x27\x00\x27\x00\x27\x00\x27\x00\x27\x00\x27\x00\x27\x00\x27\x00\x27\x00\x00\x00\x3c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x27\x00\x27\x00\x27\x00\x27\x00\x27\x00\x27\x00\x00\x00\x3f\x00\x00\x00\x27\x00\x27\x00\x27\x00\x27\x00\x27\x00\x27\x00\x29\x00\x29\x00\x29\x00\x29\x00\x29\x00\x29\x00\x29\x00\x29\x00\x3a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x27\x00\x27\x00\x27\x00\x27\x00\x27\x00\x27\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x34\x00\x39\x00\x3c\x00\x3c\x00\x3c\x00\x3c\x00\x3c\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x2f\x00\x42\x00\x42\x00\x42\x00\x42\x00\x42\x00\x3f\x00\x00\x00\x00\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x00\x00\x00\x00\x00\x00\x3a\x00\x00\x00\x42\x00\x00\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x00\x00\x40\x00\x00\x00\x00\x00\x2f\x00\x00\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x3c\x00\x3c\x00\x3c\x00\x3c\x00\x3c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x2f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3f\x00\x00\x00\x00\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x00\x00\x00\x00\x00\x00\x3a\x00\x00\x00\x00\x00\x00\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x2f\x00\x00\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x2f\x00\x32\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x00\x00\x00\x00\x00\x00\x00\x00\x32\x00\x00\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x00\x00\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x00\x00\x00\x00\x00\x00\x00\x00\x32\x00\x00\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x00\x00\x00\x00\x30\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x31\x00\x42\x00\x42\x00\x42\x00\x42\x00\x42\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x42\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x35\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x45\x00\x00\x00\x00\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x00\x00\x00\x00\x00\x00\x00\x00\x35\x00\x00\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x42\x00\x42\x00\x42\x00\x42\x00\x42\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x42\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x35\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x45\x00\x00\x00\x00\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x00\x00\x00\x00\x00\x00\x00\x00\x35\x00\x00\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x42\x00\x42\x00\x42\x00\x42\x00\x42\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x42\x00\x00\x00\x00\x00\x00\x00\x00\x00\x38\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x45\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x00\x00\x00\x00\x00\x00\x00\x00\x38\x00\x00\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x00\x00\x36\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x00\x00\x00\x00\x00\x00\x00\x00\x38\x00\x00\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x00\x00\x00\x00\x36\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x49\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x00\x00\x00\x00\x00\x00\x00\x00\x49\x00\x00\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x00\x00\x00\x00\x00\x00\x00\x00\x49\x00\x00\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x49\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"# +alex_table = AlexA# "\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x1f\x00\x1f\x00\x1f\x00\x1f\x00\x1f\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x1f\x00\x20\x00\x34\x00\x27\x00\x26\x00\x13\x00\x22\x00\x1b\x00\x27\x00\x27\x00\x27\x00\x27\x00\x27\x00\x25\x00\x27\x00\x27\x00\x09\x00\x0b\x00\x17\x00\x15\x00\x14\x00\x12\x00\x16\x00\x0c\x00\xff\xff\x20\x00\x2f\x00\x27\x00\x3d\x00\x28\x00\x22\x00\x27\x00\x30\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x27\x00\x33\x00\x27\x00\x27\x00\xff\xff\xff\xff\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x32\x00\x24\x00\x27\x00\x27\x00\x27\x00\x1f\x00\x1f\x00\x1f\x00\x1f\x00\x1f\x00\xff\xff\xff\xff\xff\xff\xff\xff\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x39\x00\x3b\x00\x00\x00\x00\x00\x1f\x00\x00\x00\x00\x00\xff\xff\x1f\x00\x1f\x00\x1f\x00\x1f\x00\x1f\x00\x08\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x21\x00\x21\x00\x23\x00\x1f\x00\x1f\x00\x1f\x00\x1f\x00\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1f\x00\x00\x00\x00\x00\x05\x00\x05\x00\x05\x00\x00\x00\x00\x00\x00\x00\x39\x00\x00\x00\x3a\x00\x40\x00\x03\x00\x1f\x00\x00\x00\x3e\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x3b\x00\x00\x00\x00\x00\x41\x00\x00\x00\x00\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1a\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x06\x00\x0a\x00\x0a\x00\x0a\x00\x0a\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x00\x00\x3c\x00\x00\x00\x00\x00\x06\x00\x00\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x07\x00\x00\x00\x36\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x00\x00\x00\x00\x38\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x19\x00\x19\x00\x19\x00\x19\x00\x19\x00\x19\x00\x19\x00\x19\x00\x19\x00\x19\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x19\x00\x00\x00\x00\x00\x00\x00\x00\x00\x19\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00\x00\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00\x00\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x0d\x00\x29\x00\x29\x00\x29\x00\x29\x00\x29\x00\x29\x00\x29\x00\x29\x00\x29\x00\x29\x00\x2a\x00\x2a\x00\x2a\x00\x2a\x00\x2a\x00\x2a\x00\x2a\x00\x2a\x00\x2a\x00\x2a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x2a\x00\x2a\x00\x2a\x00\x2a\x00\x2a\x00\x2a\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2b\x00\x2a\x00\x2a\x00\x2a\x00\x2a\x00\x2a\x00\x2a\x00\x2a\x00\x2a\x00\x2a\x00\x2a\x00\x2a\x00\x2a\x00\x2a\x00\x2a\x00\x2a\x00\x2a\x00\x00\x00\x2a\x00\x2a\x00\x2a\x00\x2a\x00\x2a\x00\x2a\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x2a\x00\x2a\x00\x2a\x00\x2a\x00\x2a\x00\x2a\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x0e\x00\x19\x00\x19\x00\x19\x00\x19\x00\x19\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x19\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00\x00\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00\x00\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x0a\x00\x0a\x00\x0a\x00\x0a\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x29\x00\x29\x00\x29\x00\x29\x00\x29\x00\x29\x00\x29\x00\x29\x00\x29\x00\x29\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x3a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x2d\x00\x35\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x00\x00\x2e\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x00\x00\x00\x00\x00\x00\x3a\x00\x00\x00\x00\x00\x00\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x00\x00\x00\x00\x00\x00\x00\x00\x35\x00\x00\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x35\x00\x0a\x00\x0a\x00\x0a\x00\x0a\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x37\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x00\x00\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x00\x00\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x00\x00\x00\x00\x00\x00\x00\x00\x37\x00\x00\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x37\x00\x3f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3f\x00\x00\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x3f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"# alex_check :: AlexAddr -alex_check = AlexA# "\xff\xff\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0a\x00\x0a\x00\x2d\x00\x2d\x00\x2d\x00\x2d\x00\x2d\x00\x77\x00\x72\x00\x61\x00\x70\x00\x70\x00\x65\x00\x2d\x00\x72\x00\x2d\x00\xff\xff\xff\xff\x20\x00\x21\x00\x22\x00\x23\x00\x24\x00\x25\x00\x26\x00\x27\x00\x28\x00\x29\x00\x2a\x00\x2b\x00\x2c\x00\x2d\x00\x2e\x00\x2f\x00\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\x3a\x00\x3b\x00\x3c\x00\x3d\x00\x3e\x00\x3f\x00\x40\x00\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\x5b\x00\x5c\x00\x5d\x00\x5e\x00\x5f\x00\x60\x00\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\x7b\x00\x7c\x00\x7d\x00\x7e\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0a\x00\x0a\x00\x0a\x00\x0a\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0a\x00\x0a\x00\xff\xff\xff\xff\x20\x00\xff\xff\xff\xff\x0a\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x20\x00\xff\xff\xff\xff\xff\xff\x2d\x00\x20\x00\xff\xff\xff\xff\xff\xff\x2d\x00\xff\xff\x22\x00\x22\x00\x2d\x00\xff\xff\xff\xff\xff\xff\xff\xff\x20\x00\xff\xff\xff\xff\x3a\x00\x3a\x00\x3a\x00\x3a\x00\xff\xff\x0a\x00\x0a\x00\x0a\x00\x0a\x00\x2c\x00\x2d\x00\xff\xff\xff\xff\x30\x00\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\x3d\x00\xff\xff\xff\xff\x3e\x00\xff\xff\xff\xff\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\x3d\x00\x3d\x00\x3d\x00\x3d\x00\xff\xff\x7b\x00\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\xff\xff\xff\xff\xff\xff\x20\x00\xff\xff\xff\xff\xff\xff\xff\xff\x20\x00\xff\xff\x27\x00\x0a\x00\xff\xff\xff\xff\xff\xff\xff\xff\x2d\x00\xff\xff\xff\xff\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\x3a\x00\xff\xff\xff\xff\xff\xff\xff\xff\x3a\x00\xff\xff\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\x3d\x00\xff\xff\xff\xff\xff\xff\x5f\x00\xff\xff\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x20\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x27\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x2d\x00\xff\xff\xff\xff\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\x3a\x00\xff\xff\xff\xff\xff\xff\xff\xff\x20\x00\xff\xff\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\xff\xff\x3d\x00\xff\xff\xff\xff\x5f\x00\xff\xff\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\x7b\x00\x20\x00\x21\x00\x22\x00\x23\x00\x24\x00\x25\x00\x26\x00\x27\x00\x28\x00\x29\x00\x2a\x00\x2b\x00\x2c\x00\x2d\x00\x2e\x00\x2f\x00\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\x3a\x00\x3b\x00\x3c\x00\x3d\x00\x3e\x00\x3f\x00\x40\x00\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\x5b\x00\x5c\x00\x5d\x00\x5e\x00\x5f\x00\x60\x00\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\x7b\x00\x7c\x00\x7d\x00\x7e\x00\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\xff\xff\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\xff\xff\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\xff\xff\x20\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\xff\xff\x2d\x00\xff\xff\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x3d\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\x7b\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x20\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x27\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x2d\x00\xff\xff\xff\xff\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\xff\xff\xff\xff\xff\xff\x3d\x00\xff\xff\x20\x00\xff\xff\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\xff\xff\x3d\x00\xff\xff\xff\xff\x5f\x00\xff\xff\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x20\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x27\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x2d\x00\xff\xff\xff\xff\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\xff\xff\xff\xff\xff\xff\x3d\x00\xff\xff\xff\xff\xff\xff\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\xff\xff\xff\xff\xff\xff\xff\xff\x5f\x00\xff\xff\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\x27\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\xff\xff\xff\xff\xff\xff\xff\xff\x5f\x00\xff\xff\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\x27\x00\xff\xff\x7d\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\xff\xff\xff\xff\xff\xff\xff\xff\x5f\x00\xff\xff\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\xff\xff\xff\xff\x7d\x00\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x20\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x27\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x2d\x00\xff\xff\xff\xff\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\xff\xff\xff\xff\xff\xff\x3d\x00\xff\xff\xff\xff\xff\xff\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\xff\xff\xff\xff\xff\xff\xff\xff\x5f\x00\xff\xff\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x20\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x27\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x2d\x00\xff\xff\xff\xff\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\xff\xff\xff\xff\xff\xff\x3d\x00\xff\xff\xff\xff\xff\xff\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\xff\xff\xff\xff\xff\xff\xff\xff\x5f\x00\xff\xff\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x20\x00\xff\xff\xff\xff\xff\xff\xff\xff\x27\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x2d\x00\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x3d\x00\xff\xff\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\xff\xff\xff\xff\xff\xff\xff\xff\x5f\x00\xff\xff\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\x27\x00\xff\xff\x7d\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\xff\xff\xff\xff\xff\xff\xff\xff\x5f\x00\xff\xff\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\xff\xff\xff\xff\x7d\x00\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\x27\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\xff\xff\xff\xff\xff\xff\xff\xff\x5f\x00\xff\xff\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\x27\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\xff\xff\xff\xff\xff\xff\xff\xff\x5f\x00\xff\xff\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"# +alex_check = AlexA# "\xff\xff\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00\x1a\x00\x1b\x00\x1c\x00\x1d\x00\x1e\x00\x1f\x00\x20\x00\x2d\x00\x22\x00\x23\x00\x24\x00\x25\x00\x2d\x00\x65\x00\x28\x00\x29\x00\x2a\x00\x2b\x00\x2c\x00\x2d\x00\x2e\x00\x2f\x00\x2d\x00\x2d\x00\x2d\x00\x61\x00\x77\x00\x72\x00\x70\x00\x70\x00\x0a\x00\x2d\x00\x3a\x00\x3b\x00\x3c\x00\x72\x00\x2d\x00\x3f\x00\x40\x00\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\x5b\x00\x5c\x00\x5d\x00\x5e\x00\x0a\x00\x0a\x00\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\x7b\x00\x7c\x00\x7d\x00\x7e\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0a\x00\x0a\x00\x0a\x00\x0a\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0a\x00\x0a\x00\xff\xff\xff\xff\xff\xff\x3d\x00\x3d\x00\xff\xff\xff\xff\x20\x00\xff\xff\xff\xff\x0a\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x20\x00\xff\xff\xff\xff\xff\xff\x2d\x00\xff\xff\x22\x00\x22\x00\x2d\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\xff\xff\xff\xff\xff\xff\xff\xff\x20\x00\xff\xff\xff\xff\x3a\x00\x3a\x00\x3a\x00\xff\xff\xff\xff\xff\xff\x3d\x00\xff\xff\x3d\x00\x2c\x00\x2d\x00\x20\x00\xff\xff\x30\x00\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\x3d\x00\xff\xff\xff\xff\x3e\x00\xff\xff\xff\xff\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7b\x00\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\x27\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\xff\xff\xff\xff\xff\xff\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x20\x00\xff\xff\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\xff\xff\x3d\x00\xff\xff\xff\xff\x5f\x00\xff\xff\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\x27\x00\xff\xff\x7d\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\xff\xff\xff\xff\xff\xff\xff\xff\x5f\x00\xff\xff\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\xff\xff\xff\xff\x7d\x00\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\xff\xff\xff\xff\xff\xff\x20\x00\xff\xff\xff\xff\xff\xff\xff\xff\x20\x00\xff\xff\x27\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x2d\x00\xff\xff\xff\xff\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\x3a\x00\xff\xff\xff\xff\xff\xff\xff\xff\x3a\x00\xff\xff\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\xff\xff\xff\xff\xff\xff\xff\xff\x5f\x00\xff\xff\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\x7b\x00\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\xff\xff\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\x7b\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x20\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x27\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x2d\x00\xff\xff\xff\xff\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\x3a\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\xff\xff\xff\xff\xff\xff\xff\xff\x5f\x00\xff\xff\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00\x1a\x00\x1b\x00\x1c\x00\x1d\x00\x1e\x00\x1f\x00\xff\xff\xff\xff\xff\xff\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\xff\xff\xff\xff\xff\xff\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\x20\x00\xff\xff\xff\xff\xff\xff\xff\xff\x20\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x2d\x00\xff\xff\xff\xff\xff\xff\xff\xff\x2d\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x3d\x00\xff\xff\xff\xff\xff\xff\xff\xff\x3d\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x20\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x6f\x00\x27\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x2d\x00\xff\xff\x78\x00\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\xff\xff\xff\xff\xff\xff\x3d\x00\xff\xff\xff\xff\xff\xff\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\xff\xff\xff\xff\xff\xff\xff\xff\x5f\x00\xff\xff\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x20\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x27\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x2d\x00\xff\xff\xff\xff\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\xff\xff\xff\xff\xff\xff\x3d\x00\xff\xff\xff\xff\xff\xff\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\xff\xff\xff\xff\xff\xff\xff\xff\x5f\x00\xff\xff\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\x27\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\xff\xff\xff\xff\xff\xff\xff\xff\x5f\x00\xff\xff\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"# alex_deflt :: AlexAddr -alex_deflt = AlexA# "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x06\x00\x06\x00\xff\xff\xff\xff\xff\xff\x0b\x00\x0b\x00\xff\xff\x15\x00\xff\xff\x15\x00\xff\xff\xff\xff\xff\xff\xff\xff\x15\x00\x15\x00\xff\xff\xff\xff\x19\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x3e\x00\xff\xff\x3e\x00\x3e\x00\xff\xff\xff\xff\x44\x00\xff\xff\x44\x00\x44\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x4c\x00"# +alex_deflt = AlexA# "\x31\x00\xff\xff\xff\xff\xff\xff\xff\xff\x17\x00\xff\xff\xff\xff\xff\xff\x09\x00\xff\xff\x0b\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x17\x00\xff\xff\xff\xff\x42\x00\xff\xff\x1c\x00\x1e\x00\xff\xff\xff\xff\x20\x00\xff\xff\xff\xff\x17\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x2c\x00\x1c\x00\xff\xff\xff\xff\xff\xff\xff\xff\x09\x00\xff\xff\x0b\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"# + +alex_accept = listArray (0::Int,66) [[],[(AlexAcc (alex_action_21))],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[(AlexAccSkip)],[(AlexAcc (alex_action_0))],[(AlexAcc (alex_action_0))],[(AlexAcc (alex_action_1))],[(AlexAcc (alex_action_2))],[(AlexAcc (alex_action_2))],[(AlexAccPred (alex_action_3) (alexRightContext 29)),(AlexAcc (alex_action_4))],[(AlexAcc (alex_action_4))],[(AlexAcc (alex_action_4))],[(AlexAcc (alex_action_4))],[(AlexAcc (alex_action_5))],[(AlexAcc (alex_action_6))],[(AlexAcc (alex_action_7))],[(AlexAcc (alex_action_8))],[(AlexAcc (alex_action_9))],[(AlexAcc (alex_action_9))],[(AlexAcc (alex_action_9))],[(AlexAcc (alex_action_10))],[(AlexAcc (alex_action_10))],[(AlexAcc (alex_action_10))],[(AlexAcc (alex_action_10))],[(AlexAcc (alex_action_10))],[(AlexAcc (alex_action_10))],[(AlexAcc (alex_action_11))],[(AlexAcc (alex_action_11))],[(AlexAcc (alex_action_12))],[(AlexAcc (alex_action_12))],[(AlexAcc (alex_action_13))],[(AlexAcc (alex_action_13))],[(AlexAcc (alex_action_14))],[(AlexAcc (alex_action_14))],[(AlexAcc (alex_action_15))],[(AlexAcc (alex_action_16))],[(AlexAcc (alex_action_17))],[(AlexAcc (alex_action_18))],[(AlexAcc (alex_action_19))],[(AlexAcc (alex_action_20))]] +{-# LINE 75 "Scan.x" #-} -alex_accept = listArray (0::Int,77) [[],[(AlexAcc (alex_action_21))],[],[],[(AlexAcc (alex_action_0))],[(AlexAcc (alex_action_0))],[(AlexAcc (alex_action_0))],[],[(AlexAcc (alex_action_4))],[(AlexAcc (alex_action_1))],[(AlexAcc (alex_action_10))],[],[(AlexAcc (alex_action_2))],[(AlexAcc (alex_action_2))],[],[],[(AlexAcc (alex_action_10))],[(AlexAcc (alex_action_10))],[],[],[],[],[],[(AlexAccPred (alex_action_3) (alexRightContext 24)),(AlexAcc (alex_action_4))],[],[(AlexAccSkip)],[(AlexAcc (alex_action_4))],[(AlexAcc (alex_action_4))],[(AlexAcc (alex_action_5))],[],[],[],[],[],[],[],[(AlexAcc (alex_action_6))],[(AlexAcc (alex_action_6))],[(AlexAcc (alex_action_10))],[(AlexAcc (alex_action_7))],[(AlexAcc (alex_action_9))],[(AlexAcc (alex_action_8))],[(AlexAcc (alex_action_9))],[(AlexAcc (alex_action_9))],[(AlexAcc (alex_action_10))],[(AlexAcc (alex_action_10))],[(AlexAcc (alex_action_11))],[(AlexAcc (alex_action_11))],[(AlexAcc (alex_action_11))],[],[],[],[(AlexAcc (alex_action_12))],[(AlexAcc (alex_action_12))],[(AlexAcc (alex_action_12))],[],[],[],[(AlexAcc (alex_action_13))],[(AlexAcc (alex_action_13))],[],[],[],[],[(AlexAcc (alex_action_14))],[(AlexAcc (alex_action_14))],[],[],[],[],[(AlexAcc (alex_action_15))],[(AlexAcc (alex_action_16))],[(AlexAcc (alex_action_17))],[(AlexAcc (alex_action_17))],[(AlexAcc (alex_action_18))],[(AlexAcc (alex_action_19))],[(AlexAcc (alex_action_20))],[]] -{-# LINE 73 "src/Scan.x" #-} -- ----------------------------------------------------------------------------- -- Token type @@ -151,7 +155,7 @@ code (p,_,inp) len = do lexError s = do - (p,_,input) <- getInput + (p,_,_,input) <- getInput failP (s ++ (if (not (null input)) then " at " ++ show (head input) else " at end of file")) @@ -161,7 +165,7 @@ lexer cont = lexToken >>= cont lexToken :: P Token lexToken = do - inp@(p,_,_) <- getInput + inp@(p,c,_,s) <- getInput sc <- getStartCode case alexScan inp sc of AlexEOF -> return (T p EOFT) @@ -171,9 +175,9 @@ lexToken = do lexToken AlexToken inp1 len t -> do setInput inp1 - t inp len + t (p,c,s) len -type Action = AlexInput -> Int -> P Token +type Action = (AlexPosn,Char,String) -> Int -> P Token skip :: Action skip _ _ = lexToken @@ -185,32 +189,33 @@ andBegin act sc inp len = setStartCode sc >> act inp len afterstartcodes,startcodes :: Int afterstartcodes = 1 startcodes = 2 -alex_action_0 = skip -alex_action_1 = string -alex_action_2 = bind -alex_action_3 = code -alex_action_4 = special -alex_action_5 = wrapper -alex_action_6 = decch -alex_action_7 = hexch -alex_action_8 = octch -alex_action_9 = escape -alex_action_10 = char -alex_action_11 = smac -alex_action_12 = rmac -alex_action_13 = smacdef -alex_action_14 = rmacdef -alex_action_15 = special `andBegin` startcodes -alex_action_16 = zero -alex_action_17 = startcode -alex_action_18 = special -alex_action_19 = special `andBegin` afterstartcodes -alex_action_20 = special `andBegin` 0 -alex_action_21 = skip `andBegin` 0 -{-# LINE 1 "GenericTemplate.hs" #-} +alex_action_0 = skip +alex_action_1 = string +alex_action_2 = bind +alex_action_3 = code +alex_action_4 = special +alex_action_5 = wrapper +alex_action_6 = decch +alex_action_7 = hexch +alex_action_8 = octch +alex_action_9 = escape +alex_action_10 = char +alex_action_11 = smac +alex_action_12 = rmac +alex_action_13 = smacdef +alex_action_14 = rmacdef +alex_action_15 = special `andBegin` startcodes +alex_action_16 = zero +alex_action_17 = startcode +alex_action_18 = special +alex_action_19 = special `andBegin` afterstartcodes +alex_action_20 = special `andBegin` 0 +alex_action_21 = skip `andBegin` 0 +{-# LINE 1 "templates/GenericTemplate.hs" #-} +{-# LINE 1 "templates/GenericTemplate.hs" #-} {-# LINE 1 "" #-} -{-# LINE 1 "" #-} -{-# LINE 1 "GenericTemplate.hs" #-} +{-# LINE 1 "" #-} +{-# LINE 1 "templates/GenericTemplate.hs" #-} -- ----------------------------------------------------------------------------- -- ALEX TEMPLATE -- @@ -220,9 +225,9 @@ alex_action_21 = skip `andBegin` 0 -- ----------------------------------------------------------------------------- -- INTERNALS and main scanner engine -{-# LINE 35 "GenericTemplate.hs" #-} +{-# LINE 37 "templates/GenericTemplate.hs" #-} -{-# LINE 45 "GenericTemplate.hs" #-} +{-# LINE 47 "templates/GenericTemplate.hs" #-} data AlexAddr = AlexA# Addr# @@ -236,10 +241,10 @@ alexIndexInt16OffAddr (AlexA# arr) off = #ifdef WORDS_BIGENDIAN narrow16Int# i where - i = word2Int# ((high `uncheckedShiftL#` 8#) `or#` low) - high = int2Word# (ord# (indexCharOffAddr# arr (off' +# 1#))) - low = int2Word# (ord# (indexCharOffAddr# arr off')) - off' = off *# 2# + !i = word2Int# ((high `uncheckedShiftL#` 8#) `or#` low) + !high = int2Word# (ord# (indexCharOffAddr# arr (off' +# 1#))) + !low = int2Word# (ord# (indexCharOffAddr# arr off')) + !off' = off *# 2# #else indexInt16OffAddr# arr off #endif @@ -253,14 +258,14 @@ alexIndexInt32OffAddr (AlexA# arr) off = #ifdef WORDS_BIGENDIAN narrow32Int# i where - i = word2Int# ((b3 `uncheckedShiftL#` 24#) `or#` + !i = word2Int# ((b3 `uncheckedShiftL#` 24#) `or#` (b2 `uncheckedShiftL#` 16#) `or#` (b1 `uncheckedShiftL#` 8#) `or#` b0) - b3 = int2Word# (ord# (indexCharOffAddr# arr (off' +# 3#))) - b2 = int2Word# (ord# (indexCharOffAddr# arr (off' +# 2#))) - b1 = int2Word# (ord# (indexCharOffAddr# arr (off' +# 1#))) - b0 = int2Word# (ord# (indexCharOffAddr# arr off')) - off' = off *# 4# + !b3 = int2Word# (ord# (indexCharOffAddr# arr (off' +# 3#))) + !b2 = int2Word# (ord# (indexCharOffAddr# arr (off' +# 2#))) + !b1 = int2Word# (ord# (indexCharOffAddr# arr (off' +# 1#))) + !b0 = int2Word# (ord# (indexCharOffAddr# arr off')) + !off' = off *# 4# #else indexInt32OffAddr# arr off #endif @@ -295,7 +300,7 @@ alexScan input (I# (sc)) alexScanUser user input (I# (sc)) = case alex_scan_tkn user input 0# input sc AlexNone of (AlexNone, input') -> - case alexGetChar input of + case alexGetByte input of Nothing -> @@ -307,17 +312,17 @@ alexScanUser user input (I# (sc)) AlexError input' - (AlexLastSkip input len, _) -> + (AlexLastSkip input'' len, _) -> - AlexSkip input len + AlexSkip input'' len - (AlexLastAcc k input len, _) -> + (AlexLastAcc k input''' len, _) -> - AlexToken input len k + AlexToken input''' len k -- Push the input through the DFA, remembering the most recent accepting @@ -326,22 +331,22 @@ alexScanUser user input (I# (sc)) alex_scan_tkn user orig_input len input s last_acc = input `seq` -- strict in the input let - new_acc = check_accs (alex_accept `quickIndex` (I# (s))) + new_acc = (check_accs (alex_accept `quickIndex` (I# (s)))) in new_acc `seq` - case alexGetChar input of + case alexGetByte input of Nothing -> (new_acc, input) Just (c, new_input) -> let - base = alexIndexInt32OffAddr alex_base s - (I# (ord_c)) = ord c - offset = (base +# ord_c) - check = alexIndexInt16OffAddr alex_check offset + !(base) = alexIndexInt32OffAddr alex_base s + !((I# (ord_c))) = fromIntegral c + !(offset) = (base +# ord_c) + !(check) = alexIndexInt16OffAddr alex_check offset - new_s = if (offset >=# 0#) && (check ==# ord_c) + !(new_s) = if (offset >=# 0#) && (check ==# ord_c) then alexIndexInt16OffAddr alex_table offset else alexIndexInt16OffAddr alex_deflt s in @@ -349,18 +354,19 @@ alex_scan_tkn user orig_input len input s last_acc = -1# -> (new_acc, input) -- on an error, we want to keep the input *before* the -- character that failed, not after. - _ -> alex_scan_tkn user orig_input (len +# 1#) + _ -> alex_scan_tkn user orig_input (if c < 0x80 || c >= 0xC0 then (len +# 1#) else len) + -- note that the length is increased ONLY if this is the 1st byte in a char encoding) new_input new_s new_acc where check_accs [] = last_acc check_accs (AlexAcc a : _) = AlexLastAcc a input (I# (len)) check_accs (AlexAccSkip : _) = AlexLastSkip input (I# (len)) - check_accs (AlexAccPred a pred : rest) - | pred user orig_input (I# (len)) input + check_accs (AlexAccPred a predx : rest) + | predx user orig_input (I# (len)) input = AlexLastAcc a input (I# (len)) - check_accs (AlexAccSkipPred pred : rest) - | pred user orig_input (I# (len)) input + check_accs (AlexAccSkipPred predx : rest) + | predx user orig_input (I# (len)) input = AlexLastSkip input (I# (len)) check_accs (_ : rest) = check_accs rest @@ -369,6 +375,11 @@ data AlexLastAcc a | AlexLastAcc a !AlexInput !Int | AlexLastSkip !AlexInput !Int +instance Functor AlexLastAcc where + fmap f AlexNone = AlexNone + fmap f (AlexLastAcc x y z) = AlexLastAcc (f x) y z + fmap f (AlexLastSkip x y) = AlexLastSkip x y + data AlexAcc a user = AlexAcc a | AlexAccSkip @@ -386,6 +397,8 @@ alexAndPred p1 p2 user in1 len in2 --alexPrevCharIsPred :: Char -> AlexAccPred _ alexPrevCharIs c _ input _ _ = c == alexInputPrevChar input +alexPrevCharMatches f _ input _ _ = f (alexInputPrevChar input) + --alexPrevCharIsOneOfPred :: Array Char Bool -> AlexAccPred _ alexPrevCharIsOneOf arr _ input _ _ = arr ! alexInputPrevChar input diff --git a/src/Scan.x b/src/Scan.x index c0d8561..a3058b0 100644 --- a/src/Scan.x +++ b/src/Scan.x @@ -186,7 +186,7 @@ code (p,_,inp) len = do lexError s = do - (p,_,input) <- getInput + (p,_,_,input) <- getInput failP (s ++ (if (not (null input)) then " at " ++ show (head input) else " at end of file")) @@ -196,7 +196,7 @@ lexer cont = lexToken >>= cont lexToken :: P Token lexToken = do - inp@(p,_,_) <- getInput + inp@(p,c,_,s) <- getInput sc <- getStartCode case alexScan inp sc of AlexEOF -> return (T p EOFT) @@ -206,9 +206,9 @@ lexToken = do lexToken AlexToken inp1 len t -> do setInput inp1 - t inp len + t (p,c,s) len -type Action = AlexInput -> Int -> P Token +type Action = (AlexPosn,Char,String) -> Int -> P Token skip :: Action skip _ _ = lexToken diff --git a/src/Set.hs b/src/Set.hs index 3f9eb22..2efc7fd 100644 --- a/src/Set.hs +++ b/src/Set.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE CPP #-} module Set ( Set, member, empty, insert ) where import Data.Set diff --git a/src/UTF8.hs b/src/UTF8.hs new file mode 100644 index 0000000..ac31d19 --- /dev/null +++ b/src/UTF8.hs @@ -0,0 +1,36 @@ +module UTF8 where + +import Data.Word +import Data.Bits +import Data.Char + +{- +-- Could also be imported: + +import Codec.Binary.UTF8.Light as UTF8 + +encode :: Char -> [Word8] +encode c = head (UTF8.encodeUTF8' [UTF8.c2w c]) + +-} + +-- | Encode a Haskell String to a list of Word8 values, in UTF8 format. +encode :: Char -> [Word8] +encode = map fromIntegral . go . ord + where + go oc + | oc <= 0x7f = [oc] + + | oc <= 0x7ff = [ 0xc0 + (oc `shiftR` 6) + , 0x80 + oc .&. 0x3f + ] + + | oc <= 0xffff = [ 0xe0 + (oc `shiftR` 12) + , 0x80 + ((oc `shiftR` 6) .&. 0x3f) + , 0x80 + oc .&. 0x3f + ] + | otherwise = [ 0xf0 + (oc `shiftR` 18) + , 0x80 + ((oc `shiftR` 12) .&. 0x3f) + , 0x80 + ((oc `shiftR` 6) .&. 0x3f) + , 0x80 + oc .&. 0x3f + ] diff --git a/templates/GenericTemplate.hs b/templates/GenericTemplate.hs index d078b36..5649a55 100644 --- a/templates/GenericTemplate.hs +++ b/templates/GenericTemplate.hs @@ -74,14 +74,14 @@ alexIndexInt32OffAddr (AlexA# arr) off = ALEX_IF_BIGENDIAN narrow32Int# i where - i = word2Int# ((b3 `uncheckedShiftL#` 24#) `or#` + !i = word2Int# ((b3 `uncheckedShiftL#` 24#) `or#` (b2 `uncheckedShiftL#` 16#) `or#` (b1 `uncheckedShiftL#` 8#) `or#` b0) - b3 = int2Word# (ord# (indexCharOffAddr# arr (off' +# 3#))) - b2 = int2Word# (ord# (indexCharOffAddr# arr (off' +# 2#))) - b1 = int2Word# (ord# (indexCharOffAddr# arr (off' +# 1#))) - b0 = int2Word# (ord# (indexCharOffAddr# arr off')) - off' = off *# 4# + !b3 = int2Word# (ord# (indexCharOffAddr# arr (off' +# 3#))) + !b2 = int2Word# (ord# (indexCharOffAddr# arr (off' +# 2#))) + !b1 = int2Word# (ord# (indexCharOffAddr# arr (off' +# 1#))) + !b0 = int2Word# (ord# (indexCharOffAddr# arr off')) + !off' = off *# 4# ALEX_ELSE indexInt32OffAddr# arr off ALEX_ENDIF @@ -116,7 +116,7 @@ alexScan input IBOX(sc) alexScanUser user input IBOX(sc) = case alex_scan_tkn user input ILIT(0) input sc AlexNone of (AlexNone, input') -> - case alexGetChar input of + case alexGetByte input of Nothing -> #ifdef ALEX_DEBUG trace ("End of input.") $ @@ -147,10 +147,10 @@ alexScanUser user input IBOX(sc) alex_scan_tkn user orig_input len input s last_acc = input `seq` -- strict in the input let - new_acc = check_accs (alex_accept `quickIndex` IBOX(s)) + new_acc = (check_accs (alex_accept `quickIndex` IBOX(s))) in new_acc `seq` - case alexGetChar input of + case alexGetByte input of Nothing -> (new_acc, input) Just (c, new_input) -> #ifdef ALEX_DEBUG @@ -158,7 +158,7 @@ alex_scan_tkn user orig_input len input s last_acc = #endif let FAST_INT_BINDING(base) = alexIndexInt32OffAddr alex_base s - FAST_INT_BINDING(IBOX(ord_c)) = ord c + FAST_INT_BINDING(IBOX(ord_c)) = fromIntegral c FAST_INT_BINDING(offset) = PLUS(base,ord_c) FAST_INT_BINDING(check) = alexIndexInt16OffAddr alex_check offset @@ -170,7 +170,8 @@ alex_scan_tkn user orig_input len input s last_acc = ILIT(-1) -> (new_acc, input) -- on an error, we want to keep the input *before* the -- character that failed, not after. - _ -> alex_scan_tkn user orig_input PLUS(len,ILIT(1)) + _ -> alex_scan_tkn user orig_input (if c < 0x80 || c >= 0xC0 then PLUS(len,ILIT(1)) else len) + -- note that the length is increased ONLY if this is the 1st byte in a char encoding) new_input new_s new_acc where @@ -190,6 +191,11 @@ data AlexLastAcc a | AlexLastAcc a !AlexInput !Int | AlexLastSkip !AlexInput !Int +instance Functor AlexLastAcc where + fmap f AlexNone = AlexNone + fmap f (AlexLastAcc x y z) = AlexLastAcc (f x) y z + fmap f (AlexLastSkip x y) = AlexLastSkip x y + data AlexAcc a user = AlexAcc a | AlexAccSkip @@ -207,6 +213,8 @@ alexAndPred p1 p2 user in1 len in2 --alexPrevCharIsPred :: Char -> AlexAccPred _ alexPrevCharIs c _ input _ _ = c == alexInputPrevChar input +alexPrevCharMatches f _ input _ _ = f (alexInputPrevChar input) + --alexPrevCharIsOneOfPred :: Array Char Bool -> AlexAccPred _ alexPrevCharIsOneOf arr _ input _ _ = arr ! alexInputPrevChar input diff --git a/templates/wrappers.hs b/templates/wrappers.hs index a92a2e2..ff4ec0f 100644 --- a/templates/wrappers.hs +++ b/templates/wrappers.hs @@ -4,6 +4,7 @@ -- This code is in the PUBLIC DOMAIN; you may copy it freely and use -- it for any purpose whatsoever. +import Data.Word (Word8) #if defined(ALEX_BASIC_BYTESTRING) || defined(ALEX_POSN_BYTESTRING) || defined(ALEX_MONAD_BYTESTRING) import qualified Data.ByteString.Lazy.Char8 as ByteString @@ -14,23 +15,55 @@ import qualified Data.ByteString.Char8 as ByteString import qualified Data.ByteString.Internal as ByteString import qualified Data.ByteString.Unsafe as ByteString +#else + +import qualified Data.Bits + +-- | Encode a Haskell String to a list of Word8 values, in UTF8 format. +utf8Encode :: Char -> [Word8] +utf8Encode = map fromIntegral . go . ord + where + go oc + | oc <= 0x7f = [oc] + + | oc <= 0x7ff = [ 0xc0 + (oc `Data.Bits.shiftR` 6) + , 0x80 + oc Data.Bits..&. 0x3f + ] + + | oc <= 0xffff = [ 0xe0 + (oc `Data.Bits.shiftR` 12) + , 0x80 + ((oc `Data.Bits.shiftR` 6) Data.Bits..&. 0x3f) + , 0x80 + oc Data.Bits..&. 0x3f + ] + | otherwise = [ 0xf0 + (oc `Data.Bits.shiftR` 18) + , 0x80 + ((oc `Data.Bits.shiftR` 12) Data.Bits..&. 0x3f) + , 0x80 + ((oc `Data.Bits.shiftR` 6) Data.Bits..&. 0x3f) + , 0x80 + oc Data.Bits..&. 0x3f + ] + #endif +type Byte = Word8 + -- ----------------------------------------------------------------------------- -- The input type #if defined(ALEX_POSN) || defined(ALEX_MONAD) || defined(ALEX_GSCAN) type AlexInput = (AlexPosn, -- current position, Char, -- previous char + [Byte], -- pending bytes on current char String) -- current input string -alexInputPrevChar :: AlexInput -> Char -alexInputPrevChar (p,c,s) = c +ignorePendingBytes (p,c,ps,s) = (p,c,s) -alexGetChar :: AlexInput -> Maybe (Char,AlexInput) -alexGetChar (p,c,[]) = Nothing -alexGetChar (p,_,(c:s)) = let p' = alexMove p c in p' `seq` - Just (c, (p', c, s)) +alexInputPrevChar :: AlexInput -> Char +alexInputPrevChar (p,c,bs,s) = c + +alexGetByte :: AlexInput -> Maybe (Byte,AlexInput) +alexGetByte (p,c,(b:bs),s) = Just (b,(p,c,bs,s)) +alexGetByte (p,c,[],[]) = Nothing +alexGetByte (p,_,[],(c:s)) = let p' = alexMove p c + (b:bs) = utf8Encode c + in p' `seq` Just (b, (p', c, bs, s)) #endif #if defined(ALEX_POSN_BYTESTRING) || defined(ALEX_MONAD_BYTESTRING) @@ -80,6 +113,7 @@ data AlexState = AlexState { alex_pos :: !AlexPosn, -- position at current input location alex_inp :: String, -- the current input alex_chr :: !Char, -- the character before the input + alex_bytes :: [Byte], alex_scd :: !Int -- the current startcode #ifdef ALEX_MONAD_USER_STATE , alex_ust :: AlexUserState -- AlexUserState will be defined in the user program @@ -93,6 +127,7 @@ runAlex input (Alex f) = case f (AlexState {alex_pos = alexStartPos, alex_inp = input, alex_chr = '\n', + alex_bytes = [], #ifdef ALEX_MONAD_USER_STATE alex_ust = alexInitUserState, #endif @@ -109,12 +144,12 @@ instance Monad Alex where alexGetInput :: Alex AlexInput alexGetInput - = Alex $ \s@AlexState{alex_pos=pos,alex_chr=c,alex_inp=inp} -> - Right (s, (pos,c,inp)) + = Alex $ \s@AlexState{alex_pos=pos,alex_chr=c,alex_bytes=bs,alex_inp=inp} -> + Right (s, (pos,c,bs,inp)) alexSetInput :: AlexInput -> Alex () -alexSetInput (pos,c,inp) - = Alex $ \s -> case s{alex_pos=pos,alex_chr=c,alex_inp=inp} of +alexSetInput (pos,c,bs,inp) + = Alex $ \s -> case s{alex_pos=pos,alex_chr=c,alex_bytes=bs,alex_inp=inp} of s@(AlexState{}) -> Right (s, ()) alexError :: String -> Alex a @@ -137,7 +172,7 @@ alexMonadScan = do alexMonadScan AlexToken inp' len action -> do alexSetInput inp' - action inp len + action (ignorePendingBytes inp) len -- ----------------------------------------------------------------------------- -- Useful token actions @@ -226,7 +261,7 @@ alexMonadScan = do alexMonadScan AlexToken inp' len action -> do alexSetInput inp' - action inp len + action (ignorePendingBytes inp) len -- ----------------------------------------------------------------------------- -- Useful token actions @@ -254,21 +289,25 @@ token t input len = return (t input len) -- Basic wrapper #ifdef ALEX_BASIC -type AlexInput = (Char,String) +type AlexInput = (Char,[Byte],String) -alexGetChar (_, []) = Nothing -alexGetChar (_, c:cs) = Just (c, (c,cs)) alexInputPrevChar (c,_) = c -- alexScanTokens :: String -> [token] -alexScanTokens str = go ('\n',str) - where go inp@(_,str) = +alexScanTokens str = go ('\n',[],str) + where go inp@(_,_bs,str) = case alexScan inp 0 of AlexEOF -> [] AlexError _ -> error "lexical error" AlexSkip inp' len -> go inp' AlexToken inp' len act -> act (take len str) : go inp' + +alexGetByte :: AlexInput -> Maybe (Byte,AlexInput) +alexGetByte (c,(b:bs),s) = Just (b,(c,bs,s)) +alexGetByte (c,[],[]) = Nothing +alexGetByte (_,[],(c:s)) = let (b:bs) = utf8Encode c + in Just (b, (c, bs, s)) #endif @@ -328,8 +367,8 @@ alexScanTokens str = go (AlexInput '\n' str) #ifdef ALEX_POSN --alexScanTokens :: String -> [token] -alexScanTokens str = go (alexStartPos,'\n',str) - where go inp@(pos,_,str) = +alexScanTokens str = go (alexStartPos,'\n',[],str) + where go inp@(pos,_,bs,str) = case alexScan inp 0 of AlexEOF -> [] AlexError ((AlexPn _ line column),_,_) -> error $ "lexical error at " ++ (show line) ++ " line, " ++ (show column) ++ " column" @@ -359,14 +398,14 @@ alexScanTokens str = go (alexStartPos,'\n',str) -- For compatibility with previous versions of Alex, and because we can. #ifdef ALEX_GSCAN -alexGScan stop state inp = alex_gscan stop alexStartPos '\n' inp (0,state) +alexGScan stop state inp = alex_gscan stop alexStartPos '\n' [] inp (0,state) -alex_gscan stop p c inp (sc,state) = - case alexScan (p,c,inp) sc of +alex_gscan stop p c bs inp (sc,state) = + case alexScan (p,c,bs,inp) sc of AlexEOF -> stop p c inp (sc,state) AlexError _ -> stop p c inp (sc,state) - AlexSkip (p',c',inp') len -> alex_gscan stop p' c' inp' (sc,state) - AlexToken (p',c',inp') len k -> - k p c inp len (\scs -> alex_gscan stop p' c' inp' scs) + AlexSkip (p',c',bs',inp') len -> alex_gscan stop p' c' bs' inp' (sc,state) + AlexToken (p',c',bs',inp') len k -> + k p c inp len (\scs -> alex_gscan stop p' c' bs' inp' scs) (sc,state) #endif diff --git a/tests/Makefile b/tests/Makefile index 734a6cf..2b0ba7c 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -9,7 +9,7 @@ else HS_PROG_EXT = .bin endif -TESTS = simple.x tokens.x tokens_posn.x tokens_gscan.x tokens_bytestring.x +TESTS = unicode.x simple.x tokens.x tokens_posn.x tokens_gscan.x tokens_bytestring.x TEST_ALEX_OPTS = --template=.. @@ -28,13 +28,16 @@ ALL_TEST_HS = $(shell echo $(TESTS) | sed -e 's/\([^\. ]*\)\.\(l\)\{0,1\}x/\1.n. ALL_TESTS = $(patsubst %.hs, %.run, $(ALL_TEST_HS)) -HC_OPTS += -package array -package bytestring -#-fglasgow-exts - %.run : %$(HS_PROG_EXT) ./$< %$(HS_PROG_EXT) : %.o - $(HC) $(HC_OPTS) $($*_LD_OPTS) $< -o $@ + $(HC) $(HC_OPTS) -package array $($*_LD_OPTS) $< -o $@ all :: $(ALL_TESTS) + + +interact: + ghci -cpp -i../src -i../dist/build/autogen -i../dist/build/alex/alex-tmp Main -fbreak-on-exception +# -args='--template=.. simple.x -o simple.n.hs' +# :set args --template=.. simple.x -o simple.n.hs diff --git a/tests/unicode.x b/tests/unicode.x new file mode 100644 index 0000000..e6938b5 --- /dev/null +++ b/tests/unicode.x @@ -0,0 +1,82 @@ +{ +-- Tests the basic operation. +module Main where + +import Data.Char (toUpper) +import Control.Monad +import System.Exit +import System.IO +} + +%wrapper "monad" + +@word = [A-Za-z]+ + +tokens :- + +<0> { + + "αω" { string } + [AΓ] { character } + . { other } +} + + +{ +string (p,_,input) len = return "string!" + +other (p,_,input) len = return (take len input) + +character (p,_,input) len = return "PING!" + +alexEOF = return "stopped." + +scanner str = runAlex str $ do + let loop = do tok <- alexMonadScan + if tok == "stopped." || tok == "error." + then return [tok] + else do toks <- loop + return (tok:toks) + loop + +main = do + let test1 = scanner str1 + when (test1 /= out1) $ + do hPutStrLn stderr "Test 1 failed:" + print test1 + exitFailure + + let test2 = scanner str2 + when (test2 /= out2) $ + do hPutStrLn stderr "Test 2 failed:" + print test2 + exitFailure + + let test3 = scanner str3 + when (test3 /= out3) $ + do hPutStrLn stderr "Test 3 failed:" + print test3 + exitFailure + + let test4 = scanner str4 + when (test4 /= out4) $ + do hPutStrLn stderr "Test 4 failed:" + print test4 + exitFailure + + + +str1 = "A." +out1 = Right ["PING!",".","stopped."] + +str2 = "\n" +out2 = Left "lexical error" + + +str3 = "αω --" +out3 = Right ["string!"," ","-","-","stopped."] + +str4 = "βΓ" +out4 = Right ["β","PING!","stopped."] + +}