add integer literal tokenezation

This commit is contained in:
Ilya Rezvov
2018-01-18 16:55:15 -08:00
parent 10011f6fb2
commit 94d2c2f0a3
4 changed files with 40 additions and 49 deletions
+1 -2
View File
@@ -20,9 +20,8 @@ library:
- -fwarn-incomplete-patterns - -fwarn-incomplete-patterns
- -fwarn-unused-imports - -fwarn-unused-imports
exposed-modules: exposed-modules:
- Language.Wasm.Types
- Language.Wasm.Lexer - Language.Wasm.Lexer
- Language.Wasm.Parser - Language.Wasm
dependencies: dependencies:
- array >= 0.5 && <0.6 - array >= 0.5 && <0.6
- text >= 1.1 - text >= 1.1
+1 -1
View File
@@ -1,4 +1,4 @@
module ( module Language.Wasm (
something something
) where ) where
+36 -41
View File
@@ -5,8 +5,8 @@ module Language.Wasm.Lexer (
) where ) where
import qualified Data.ByteString.Lazy as LBS import qualified Data.ByteString.Lazy as LBS
import qualified Data.ByteString.Lazy.Char8 as LBSChar8
import qualified Data.Char as Char import qualified Data.Char as Char
import qualified Data.ByteString.Lazy.UTF8 as LBSUtf8
} }
@@ -21,6 +21,7 @@ $namepunct = [\! \# \$ \% \& \ \* \+ \ \. \/ \: \< \= \> \? \@ \ \^ \_
$idchar = [$digit $alpha $namepunct] $idchar = [$digit $alpha $namepunct]
$space = [\ \x09 \x0A \x0D] $space = [\ \x09 \x0A \x0D]
$linechar = [^ \x09] $linechar = [^ \x09]
$sign = [\+ \-]
@keyword = $lower $idchar* @keyword = $lower $idchar*
@reserved = $idchar+ @reserved = $idchar+
@@ -29,7 +30,6 @@ $linechar = [^ \x09]
@endblockcomment = "(;" @endblockcomment = "(;"
@num = $digit (\_? $digit*) @num = $digit (\_? $digit*)
@hexnum = $hexdigit (\_? $hexdigit*) @hexnum = $hexdigit (\_? $hexdigit*)
@unsignedint = @num | "0x" @hexnum
tokens :- tokens :-
@@ -38,8 +38,8 @@ tokens :-
<0> @linecomment ; <0> @linecomment ;
<0> "(" { constToken TOpenBracket } <0> "(" { constToken TOpenBracket }
<0> "(" { constToken TCloseBracket } <0> "(" { constToken TCloseBracket }
<0> @num { parseDecimalUnsignedInt } <0> $sign? @num { parseDecimalSignedInt }
<0> "0x" @hexnum { parseHexalUnsignedInt } <0> $sign? "0x" @hexnum { parseHexalSignedInt }
<0, blockComment> @startblockcomment { startBlockComment } <0, blockComment> @startblockcomment { startBlockComment }
<blockComment> [.\n] ; <blockComment> [.\n] ;
<blockComment> @endblockcomment { endBlockComment } <blockComment> @endblockcomment { endBlockComment }
@@ -66,19 +66,29 @@ defaultStartCode = 0
-- inner string literal character predicate -- inner string literal character predicate
isAllowedStringChar :: user -> AlexInput -> Int -> AlexInput -> Bool isAllowedStringChar :: user -> AlexInput -> Int -> AlexInput -> Bool
isAllowedStringChar _userState _prevInp _len (_pos, _rest, inp, _) = isAllowedStringChar _userState _prevInp _len (_pos, _rest, inp, _) =
let char = LBSChar8.head inp in let Just (char, _) = LBSUtf8.decode inp in
let code = Char.ord char in let code = Char.ord char in
code >= 0x20 && code /= 0x7f && char /= '"' && char /= '\\' code >= 0x20 && code /= 0x7f && char /= '"' && char /= '\\'
parseHexalUnsignedInt :: AlexAction Lexeme parseSign :: LBS.ByteString -> ((Integer -> Integer), Int64)
parseHexalUnsignedInt = token $ \(pos, _, s, _) len -> parseSign str =
let num = readHexFromPrefix (fromIntegral len - 2) $ dropChars 2 s in let Just (ch, _) = LBSUtf8.decode str in
Lexeme pos $ TUnsignIntLit $ fromIntegral num case ch of
'-' -> (negate, 1)
'+' -> (abs, 1)
otherwise -> (abs, 0)
parseDecimalUnsignedInt :: AlexAction Lexeme parseHexalSignedInt :: AlexAction Lexeme
parseDecimalUnsignedInt = token $ \(pos, _, s, _) len -> parseHexalSignedInt = token $ \(pos, _, s, _) len ->
let num = readDecFromPrefix (fromIntegral len) $ dropChars 2 s in let (sign, slen) = parseSign s in
Lexeme pos $ TUnsignIntLit $ fromIntegral num let num = readHexFromPrefix (len - 2 - slen) $ LBSUtf8.drop (2 + slen) s in
Lexeme pos $ TIntLit $ sign num
parseDecimalSignedInt :: AlexAction Lexeme
parseDecimalSignedInt = token $ \(pos, _, s, _) len ->
let (sign, slen) = parseSign s in
let num = readDecFromPrefix (len - slen) $ LBSUtf8.drop slen s in
Lexeme pos $ TIntLit $ sign num
startBlockComment :: AlexAction Lexeme startBlockComment :: AlexAction Lexeme
startBlockComment _inp _len = do startBlockComment _inp _len = do
@@ -115,22 +125,23 @@ appendCharToStringLiteral chr _inp _len = do
appendFromHead :: AlexAction Lexeme appendFromHead :: AlexAction Lexeme
appendFromHead (_pos, _rest, inp, _) _len = do appendFromHead (_pos, _rest, inp, _) _len = do
addCharToLexerStringValue $ LBSChar8.head inp let Just (first, _) = LBSUtf8.decode inp
addCharToLexerStringValue first
alexMonadScan alexMonadScan
appendDoubleHexChar :: AlexAction Lexeme appendDoubleHexChar :: AlexAction Lexeme
appendDoubleHexChar (_pos, _rest, inp, _) _len = do appendDoubleHexChar (_pos, _rest, inp, _) _len = do
addCharToLexerStringValue $ Char.chr $ readHexFromPrefix 2 $ dropChars 1 inp addCharToLexerStringValue $ Char.chr $ fromIntegral $ readHexFromPrefix 2 $ LBSUtf8.drop 1 inp
alexMonadScan alexMonadScan
-- TODO: add a predicate with code ranges check -- TODO: add a predicate with code ranges check
-- if 𝑛 < 0xD800 0xE000 ≤ 𝑛 < 0x110000 -- if 𝑛 < 0xD800 0xE000 ≤ 𝑛 < 0x110000
appendHexEscapedChar :: AlexAction Lexeme appendHexEscapedChar :: AlexAction Lexeme
appendHexEscapedChar (pos, _rest, inp, _) len = do appendHexEscapedChar (pos, _rest, inp, _) len = do
let code = readHexFromPrefix (fromIntegral len - 3) $ dropChars 2 inp let code = readHexFromPrefix (len - 3) $ LBSUtf8.drop 2 inp
if code < 0xD800 || (code >= 0xE000 && code < 0x110000) if code < 0xD800 || (code >= 0xE000 && code < 0x110000)
then do then do
addCharToLexerStringValue $ Char.chr code addCharToLexerStringValue $ Char.chr $ fromIntegral code
alexMonadScan alexMonadScan
else else
alexError $ "Character code should be in valid UTF range (code < 0xD800 || (code >= 0xE000 && code < 0x110000)): " ++ show pos alexError $ "Character code should be in valid UTF range (code < 0xD800 || (code >= 0xE000 && code < 0x110000)): " ++ show pos
@@ -151,8 +162,7 @@ constToken tok = token $ \(pos, _, _, _) _len -> (Lexeme pos tok)
{- End Lexem Helpers -} {- End Lexem Helpers -}
data Token = TKeyword LBS.ByteString data Token = TKeyword LBS.ByteString
| TUnsignIntLit Integer | TIntLit Integer
| TSignIntLit Integer
| TFloatLit Double | TFloatLit Double
| TStringLit LBS.ByteString | TStringLit LBS.ByteString
| TId LBS.ByteString | TId LBS.ByteString
@@ -202,26 +212,11 @@ setLexerStringValue ss = Alex $ \s ->
addCharToLexerStringValue :: Char -> Alex () addCharToLexerStringValue :: Char -> Alex ()
addCharToLexerStringValue c = Alex $ \s -> addCharToLexerStringValue c = Alex $ \s ->
let ust = alex_ust s in let ust = alex_ust s in
Right (s{ alex_ust = ust{ lexerStringValue = LBSChar8.cons c (lexerStringValue ust) } }, ()) Right (s{ alex_ust = ust{ lexerStringValue = LBS.append (LBSUtf8.fromString [c]) (lexerStringValue ust) } }, ())
alexEOF = return $ Lexeme undefined EOF alexEOF = return $ Lexeme undefined EOF
takeChars :: Int -> LBS.ByteString -> String readHexFromChar :: Char -> Integer
takeChars n str = reverse $ go n str []
where
go :: Int -> LBS.ByteString -> String -> String
go 0 _ acc = acc
go n str acc =
let Just (ch, rest) = LBSChar8.uncons str in
go (n - 1) rest (ch : acc)
dropChars :: Int -> LBS.ByteString -> LBS.ByteString
dropChars 0 str = str
dropChars n str =
let Just (_, rest) = LBSChar8.uncons str in
dropChars (n - 1) rest
readHexFromChar :: Char -> Int
readHexFromChar chr = readHexFromChar chr =
case chr of case chr of
'0' -> 0 '0' -> 0
@@ -248,18 +243,18 @@ readHexFromChar chr =
'f' -> 15 'f' -> 15
otherwise -> 0 otherwise -> 0
readFromPrefix :: Int -> Int -> LBS.ByteString -> Int readFromPrefix :: Int -> Int64 -> LBS.ByteString -> Integer
readFromPrefix base n bstr readFromPrefix base n bstr
| base <= 16 = | base <= 16 =
let str = filter (/= '_') $ takeChars n bstr in let str = filter (/= '_') $ LBSUtf8.toString $ LBSUtf8.take n bstr in
let len = length str in let len = length str in
sum $ zipWith (\i c -> readHexFromChar c * (base ^ len - i)) [1..] str sum $ zipWith (\i c -> readHexFromChar c * (fromIntegral base ^ fromIntegral (len - i))) [1..] str
| otherwise = error "base has to be less than or equal 16" | otherwise = error "base has to be less than or equal 16"
readHexFromPrefix :: Int -> LBS.ByteString -> Int readHexFromPrefix :: Int64 -> LBS.ByteString -> Integer
readHexFromPrefix = readFromPrefix 16 readHexFromPrefix = readFromPrefix 16
readDecFromPrefix :: Int -> LBS.ByteString -> Int readDecFromPrefix :: Int64 -> LBS.ByteString -> Integer
readDecFromPrefix = readFromPrefix 10 readDecFromPrefix = readFromPrefix 10
scan :: LBS.ByteString -> [Lexeme] scan :: LBS.ByteString -> [Lexeme]
+2 -5
View File
@@ -2,7 +2,7 @@
-- --
-- see: https://github.com/sol/hpack -- see: https://github.com/sol/hpack
-- --
-- hash: 3022a4b4ff00047ff39872dae4704b089f179ce1286fc792db423160c88b75f8 -- hash: 1b02a1858ead3517927e9405dabc17ffb37f0df038564d37e8321b18227389ec
name: wasm name: wasm
version: 0.1.0 version: 0.1.0
@@ -33,12 +33,9 @@ library
alex >=3.1.3 alex >=3.1.3
, happy >=1.9.4 , happy >=1.9.4
exposed-modules: exposed-modules:
Language.Wasm.Types
Language.Wasm.Lexer Language.Wasm.Lexer
Language.Wasm.Parser
other-modules:
Language.Wasm Language.Wasm
Language.Wasm.Lexer other-modules:
Paths_wasm Paths_wasm
default-language: Haskell2010 default-language: Haskell2010