Rework module system
Don't require/allow naming a module, instead require that the importer names it. Allow importing into the local scope with the name !Local. Simplify namespacing logic. Updates all tests to reflect these changes.
This commit is contained in:
124
src/Lexer.hs
124
src/Lexer.hs
@ -12,39 +12,71 @@ import qualified Data.Set as Set
|
||||
|
||||
type Lexer = Parsec Void String
|
||||
|
||||
tricuLexer :: Lexer [LToken]
|
||||
tricuLexer = do
|
||||
sc
|
||||
header <- many $ do
|
||||
tok <- choice
|
||||
[ try lImport
|
||||
, lnewline
|
||||
]
|
||||
sc
|
||||
pure tok
|
||||
tokens <- many $ do
|
||||
tok <- choice tricuLexer'
|
||||
sc
|
||||
pure tok
|
||||
sc
|
||||
eof
|
||||
pure (header ++ tokens)
|
||||
where
|
||||
tricuLexer' =
|
||||
[ try lnewline
|
||||
, try namespace
|
||||
, try dot
|
||||
, try identifier
|
||||
, try keywordT
|
||||
, try integerLiteral
|
||||
, try stringLiteral
|
||||
, assign
|
||||
, colon
|
||||
, backslash
|
||||
, openParen
|
||||
, closeParen
|
||||
, openBracket
|
||||
, closeBracket
|
||||
]
|
||||
|
||||
lexTricu :: String -> [LToken]
|
||||
lexTricu input = case runParser tricuLexer "" input of
|
||||
Left err -> errorWithoutStackTrace $ "Lexical error:\n" ++ errorBundlePretty err
|
||||
Right tokens -> tokens
|
||||
|
||||
|
||||
keywordT :: Lexer LToken
|
||||
keywordT = string "t" *> notFollowedBy alphaNumChar *> pure LKeywordT
|
||||
|
||||
identifier :: Lexer LToken
|
||||
identifier = do
|
||||
first <- letterChar <|> char '_'
|
||||
first <- lowerChar <|> char '_'
|
||||
rest <- many $ letterChar
|
||||
<|> digitChar
|
||||
<|> char '_' <|> char '-' <|> char '?' <|> char '.'
|
||||
<|> char '$' <|> char '#' <|> char '@' <|> char '%'
|
||||
<|> digitChar <|> char '_' <|> char '-' <|> char '?'
|
||||
<|> char '$' <|> char '#' <|> char '@' <|> char '%'
|
||||
let name = first : rest
|
||||
if (name == "t" || name == "!result")
|
||||
then fail "Keywords (`t`, `!result`) cannot be used as an identifier"
|
||||
else return (LIdentifier name)
|
||||
|
||||
integerLiteral :: Lexer LToken
|
||||
integerLiteral = do
|
||||
num <- some digitChar
|
||||
return (LIntegerLiteral (read num))
|
||||
namespace :: Lexer LToken
|
||||
namespace = do
|
||||
name <- try (string "!Local") <|> do
|
||||
first <- upperChar
|
||||
rest <- many (letterChar <|> digitChar)
|
||||
return (first:rest)
|
||||
return (LNamespace name)
|
||||
|
||||
stringLiteral :: Lexer LToken
|
||||
stringLiteral = do
|
||||
char '"'
|
||||
content <- many (noneOf ['"'])
|
||||
char '"' --"
|
||||
return (LStringLiteral content)
|
||||
|
||||
lModule :: Lexer LToken
|
||||
lModule = do
|
||||
_ <- string "!module"
|
||||
space1
|
||||
LIdentifier moduleName <- identifier
|
||||
return (LModule moduleName)
|
||||
dot :: Lexer LToken
|
||||
dot = char '.' *> pure LDot
|
||||
|
||||
lImport :: Lexer LToken
|
||||
lImport = do
|
||||
@ -52,7 +84,7 @@ lImport = do
|
||||
space1
|
||||
LStringLiteral path <- stringLiteral
|
||||
space1
|
||||
LIdentifier name <- identifier
|
||||
LNamespace name <- namespace
|
||||
return (LImport path name)
|
||||
|
||||
assign :: Lexer LToken
|
||||
@ -85,41 +117,15 @@ sc = space
|
||||
(skipLineComment "--")
|
||||
(skipBlockComment "|-" "-|")
|
||||
|
||||
tricuLexer :: Lexer [LToken]
|
||||
tricuLexer = do
|
||||
sc
|
||||
header <- many $ do
|
||||
tok <- choice
|
||||
[ try lModule
|
||||
, try lImport
|
||||
, lnewline
|
||||
]
|
||||
sc
|
||||
pure tok
|
||||
tokens <- many $ do
|
||||
tok <- choice tricuLexer'
|
||||
sc
|
||||
pure tok
|
||||
sc
|
||||
eof
|
||||
pure (header ++ tokens)
|
||||
where
|
||||
tricuLexer' =
|
||||
[ try lnewline
|
||||
, try identifier
|
||||
, try keywordT
|
||||
, try integerLiteral
|
||||
, try stringLiteral
|
||||
, assign
|
||||
, colon
|
||||
, backslash
|
||||
, openParen
|
||||
, closeParen
|
||||
, openBracket
|
||||
, closeBracket
|
||||
]
|
||||
integerLiteral :: Lexer LToken
|
||||
integerLiteral = do
|
||||
num <- some digitChar
|
||||
return (LIntegerLiteral (read num))
|
||||
|
||||
stringLiteral :: Lexer LToken
|
||||
stringLiteral = do
|
||||
char '"'
|
||||
content <- many (noneOf ['"'])
|
||||
char '"' --"
|
||||
return (LStringLiteral content)
|
||||
|
||||
lexTricu :: String -> [LToken]
|
||||
lexTricu input = case runParser tricuLexer "" input of
|
||||
Left err -> errorWithoutStackTrace $ "Lexical error:\n" ++ errorBundlePretty err
|
||||
Right tokens -> tokens
|
||||
|
Reference in New Issue
Block a user