gdritter repos virgil / 628bb8e
Added float parsing, although maybe in a less efficient way than I could have Getty Ritter 7 years ago
3 changed file(s) with 45 addition(s) and 5 deletion(s). Collapse all Expand all
55 module Language.Virgil.Lexer where
66
77 import Control.Monad (liftM)
8 import Data.Monoid ((<>))
9 import Data.Scientific
810 import Data.Text (Text)
911 import qualified Data.Text as T
1012
1618 $digit = 0-9
1719 $alpha = [A-Za-z]
1820
21 @int = $digit+
22 @exp = [Ee] [\-\+]? @int
23 @frac = @int \. @int @exp? | @int @exp
24 @sign = \-?
25
26 @str = \"[^\"]*\"
27
1928 tokens :-
2029 $white+ ;
2130 "#".* ;
2231
23 $digit+ { lex (TkInt . read . T.unpack) }
24 \"[^\"]*\" { lex strLiteral } -- this is for syntax highlighting -> "
32 @sign @int \. @int { lex (float True False) }
33 @sign @int \. @int @exp { lex (float True True) }
34 @sign @int @exp { lex (float False True) }
35
36 @sign @int { lex (TkInt . read . T.unpack) }
37 @str { lex strLiteral }
2538
2639 true { lex' (TkKw KwTrue) }
2740 false { lex' (TkKw KwFalse) }
3144 \} { lex' TkRCurl }
3245 \[ { lex' TkLBrac }
3346 \] { lex' TkRBrac }
47 \( { lex' TkLParn }
48 \) { lex' TkRParn }
3449
3550 {
3651 data Token = Token AlexPosn TkType deriving (Eq, Show)
4358
4459 data TkType
4560 = TkInt Integer
61 | TkFloat Scientific
4662 | TkStr Text
4763 | TkKw KwType
4864 | TkLCurl
4965 | TkRCurl
5066 | TkLBrac
5167 | TkRBrac
68 | TkLParn
69 | TkRParn
5270 | TkEOF
5371 deriving (Eq, Show)
72
73 -- Parsing floats with exponents and whatnot
74 -- XXX: MAKE MORE EFFICIENT AND LESS GROSS
75 float :: Bool -> Bool -> Text -> TkType
76 float False False _ = error "[unreachable]"
77 float True False t = -- dot but not exponent
78 let [a,b] = T.splitOn "." t
79 in TkFloat (scientific (read (T.unpack (a <> b))) (negate (T.length b)))
80 float False True t = -- exponent but no dot
81 let [a,e] = if T.any (== 'e') t
82 then T.splitOn "e" t
83 else T.splitOn "E" t
84 in TkFloat (scientific (read (T.unpack a)) (read (T.unpack e)))
85 float True True t = -- exponent and dot
86 let [t',e] = if T.any (== 'e') t
87 then T.splitOn "e" t
88 else T.splitOn "E" t
89 [a, b] = T.splitOn "." t'
90 in TkFloat (scientific (read (T.unpack (a <> b)))
91 (negate (T.length b) + read (T.unpack e)))
5492
5593 strLiteral :: Text -> TkType
5694 strLiteral = TkStr . T.drop 1 . T.dropEnd 1
2424 false { Token _ (TkKw KwFalse) }
2525 null { Token _ (TkKw KwNull) }
2626
27 int { Token _ (TkInt $$) }
28 str { Token _ (TkStr $$) }
27 int { Token _ (TkInt $$) }
28 float { Token _ (TkFloat $$) }
29 str { Token _ (TkStr $$) }
2930
3031 %%
3132
3637 expr
3738 : tlexpr { $1 }
3839 | int { ChNumber (fromIntegral $1) }
40 | float { ChNumber $1 }
3941 | str { ChString $1 }
4042 | true { ChBool True }
4143 | false { ChBool False}
66
77 "one" 1 # integers
88
9 # "two" 2.0 # floats
9 "two" 2.0 # floats
1010
1111 # lists use square brackets
1212 "three"