Skip to content

Commit

Permalink
Fix bare identifier able to start with keyword
Browse files Browse the repository at this point in the history
Fix #184
  • Loading branch information
dahlia committed Oct 26, 2017
1 parent b6cbe68 commit 93ed1ec
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 27 deletions.
34 changes: 9 additions & 25 deletions src/Nirum/Parser.hs
Expand Up @@ -33,30 +33,12 @@ module Nirum.Parser ( Parser

import Control.Applicative ((<$>))
import Control.Monad (join, void)
import Data.List (foldl1')
import qualified System.IO as SIO

import Data.Set (elems)
import Data.Set hiding (empty, foldl, fromList, map)
import qualified Data.Text as T
import qualified Data.Text.IO as TIO
import Text.Megaparsec ( Token
, choice
, eof
, many
, manyTill
, notFollowedBy
, option
, optional
, runParser
, sepBy1
, sepEndBy
, sepEndBy1
, skipMany
, skipSome
, try
, (<|>)
, (<?>)
)
import Text.Megaparsec hiding (ParseError, label, parse)
import Text.Megaparsec.Char ( char
, eol
, noneOf
Expand Down Expand Up @@ -129,12 +111,14 @@ identifier :: Parser Identifier
identifier =
quotedIdentifier <|> bareIdentifier <?> "identifier"
where
keywords :: Parser String
keywords = foldl1' (<|>) $ map (string' . toString) $ elems reservedKeywords
bareIdentifier :: Parser Identifier
bareIdentifier = do
notFollowedBy keywords
identifierRule
bareIdentifier = try $ do
ident <- lookAhead identifierRule
if ident `member` reservedKeywords
then fail $ "\"" ++ toString ident ++ "\" is a reserved keyword; "
++ "wrap it with backquotes to use it as a normal "
++ "identifier (i.e. \"`" ++ toString ident ++ "`\")"
else identifierRule
quotedIdentifier :: Parser Identifier
quotedIdentifier = do
char '`'
Expand Down
7 changes: 5 additions & 2 deletions test/Nirum/ParserSpec.hs
Expand Up @@ -134,6 +134,9 @@ spec = do
identifier' "valid-identifier"
parse' "valid_identifier" `shouldBeRight`
identifier' "valid_identifier"
it "can parse even if a keyword is a prefix of identifier" $ do
parse' "enumeration" `shouldBeRight` identifier' "enumeration"
parse' "types" `shouldBeRight` identifier' "types"
it "can parse reserved keywords iff they are quoted" $
forM_ keywords $ \ kwd ->
parse' ('`' `T.cons` kwd `T.snoc` '`') `shouldBeRight`
Expand Down Expand Up @@ -642,8 +645,8 @@ record dup (
text c/b,
);|] 5 1
it "fails to parse if there's no space between field type and name" $ do
expectError "record a (typename);" 1 11
expectError "record a (typename\n#docs\n);" 1 11
expectError "record a (texta);" 1 16
expectError "record a (textb\n#docs\n);" 2 1
it "fails to parse if trailing semicolon is missing" $ do
let (_, expectErr) = helperFuncs P.module'
expectErr
Expand Down

0 comments on commit 93ed1ec

Please sign in to comment.