git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
Allow JS reserved identifiers
29fdee5Gary Burgess
examples/passing/JSReserved.pursnew file+30
@@ -0,0 +1,30 @@
1+module Main where
2+
3+ import Prelude
4+
5+ const = "test"
6+ member = "test"
7+
8+ fortest = {
9+ var return = 0;
10+ for (i <- 0 until 10) {
11+ return = return + i;
12+ }
13+ return return;
14+ }
15+
16+ whiletest = {
17+ var for = 0;
18+ while (for > 0) {
19+ for = for - 1;
20+ }
21+ return for;
22+ }
23+
24+ vartest = {
25+ var var = 1;
26+ var = var + 1;
27+ return var;
28+ }
29+
30+ main = Trace.trace "Done"
src/Language/PureScript/Parser/Common.hs+106−68
@@ -27,60 +27,106 @@ import qualified Text.Parsec.Token as PT
27import Language.PureScript.Names
27import Language.PureScript.Names
28
28
29-- |
29-- |
30−-- A list of reserved identifiers
30+-- A list of purescript reserved identifiers
31−--
31+--
32−reservedNames :: [String]
32+reservedPsNames :: [String]
33−reservedNames = [ "case"
33+reservedPsNames = [ "data"
34− , "of"
35− , "data"
36− , "type"
34+ , "type"
37− , "var"
35+ , "foreign"
38− , "val"
36+ , "import"
39− , "while"
37+ , "infixl"
40− , "for"
38+ , "infixr"
41− , "foreach"
39+ , "class"
40+ , "instance"
41+ , "module"
42+ , "case"
43+ , "of"
42− , "if"
44+ , "if"
43− , "then"
45+ , "then"
44− , "else"
46+ , "else"
45− , "return"
47+ , "do"
48+ , "let"
46− , "true"
49+ , "true"
47− , "false"
50+ , "false"
48− , "foreign"
49− , "import"
50− , "member"
51− , "forall"
52− , "do"
53− , "until"
51+ , "until"
54− , "in"
52+ ]
53+
54+-- |
55+-- A list of javascript reserved identifiers
56+--
57+reservedJsNames :: [String]
58+reservedJsNames = [ "abstract"
59+ , "boolean"
55− , "break"
60+ , "break"
61+ , "byte"
62+ , "case"
56− , "catch"
63+ , "catch"
64+ , "char"
65+ , "class"
66+ , "const"
57− , "continue"
67+ , "continue"
58− , "debugger"
68+ , "debugger"
59− , "default"
69+ , "default"
60− , "delete"
70+ , "delete"
71+ , "do"
72+ , "double"
73+ , "else"
74+ , "enum"
75+ , "export"
76+ , "extends"
77+ , "final"
61− , "finally"
78+ , "finally"
79+ , "float"
80+ , "for"
62− , "function"
81+ , "function"
82+ , "goto"
83+ , "if"
84+ , "implements"
85+ , "import"
86+ , "in"
63− , "instanceof"
87+ , "instanceof"
88+ , "int"
89+ , "interface"
90+ , "let"
91+ , "long"
92+ , "native"
64− , "new"
93+ , "new"
94+ , "package"
95+ , "private"
96+ , "protected"
97+ , "public"
98+ , "return"
99+ , "short"
100+ , "static"
101+ , "super"
65− , "switch"
102+ , "switch"
103+ , "synchronized"
66− , "this"
104+ , "this"
67− , "throw"
105+ , "throw"
106+ , "throws"
107+ , "transient"
68− , "try"
108+ , "try"
69− , "typeof"
109+ , "typeof"
110+ , "var"
70− , "void"
111+ , "void"
112+ , "volatile"
113+ , "while"
71− , "with"
114+ , "with"
72− , "Number"
115+ , "yield" ]
73− , "String"
116+
74− , "Boolean"
117+-- |
75− , "infixl"
118+-- A list of reserved identifiers for types
76− , "infixr"
119+--
77− , "module"
120+reservedTypeNames :: [String]
78− , "let"
121+reservedTypeNames = [ "forall"
79− , "class"
80− , "instance"
81− , "where"
122+ , "where" ]
82− , "null"
123+
83− , "undefined" ]
124+-- |
125+-- A list of reserved identifiers for block statements
126+--
127+reservedStatementNames :: [String]
128+reservedStatementNames = [ "for"
129+ , "return" ]
84
130
85-- |
131-- |
86-- A list of reserved operators
132-- A list of reserved operators
@@ -123,7 +169,7 @@ opLetter = P.oneOf ":!#$%&*+./<=>?@\\^|-~"
123--
169--
124langDef :: PT.GenLanguageDef String u Identity
170langDef :: PT.GenLanguageDef String u Identity
125langDef = PT.LanguageDef
171langDef = PT.LanguageDef
126− { PT.reservedNames = reservedNames
172+ { PT.reservedNames = reservedPsNames
127 , PT.reservedOpNames = reservedOpNames
173 , PT.reservedOpNames = reservedOpNames
128 , PT.commentStart = "{-"
174 , PT.commentStart = "{-"
129 , PT.commentEnd = "-}"
175 , PT.commentEnd = "-}"
@@ -253,20 +299,12 @@ integerOrFloat = (Left <$> P.try (PT.natural tokenParser) <|>
253-- Parse an identifier or parenthesized operator
299-- Parse an identifier or parenthesized operator
254--
300--
255parseIdent :: P.Parsec String ParseState Ident
301parseIdent :: P.Parsec String ParseState Ident
256−parseIdent = (Ident <$> identifier) <|> (Op <$> parens operator)
302+parseIdent = parseIdent' <|> (Op <$> parens operator)
257−
258−
259−-- |
260−-- Parse an identifier or parenthesized operator that is not a reserved keyword or operator
261−--
262−parseNonReservedIdent :: P.Parsec String ParseState Ident
263−parseNonReservedIdent = do
264− ident <- parseIdent
265− when (isReserved ident) $ P.unexpected $ "reserved identifier " ++ show ident
266− return ident
267 where
303 where
268− isReserved (Ident ident) = ident `elem` reservedNames
304+ parseIdent' :: P.Parsec String ParseState Ident
269− isReserved (Op op) = op `elem` reservedOpNames
305+ parseIdent' = do
306+ ident <- identifier
307+ return $ if (ident `elem` reservedJsNames) then (Escaped $ "$" ++ ident) else (Ident ident)
270
308
271-- |
309-- |
272-- Parse a token inside square brackets
310-- Parse a token inside square brackets
src/Language/PureScript/Parser/Declarations.hs+3−3
@@ -46,7 +46,7 @@ parseDataDeclaration = do
46
46
47parseTypeDeclaration :: P.Parsec String ParseState Declaration
47parseTypeDeclaration :: P.Parsec String ParseState Declaration
48parseTypeDeclaration =
48parseTypeDeclaration =
49− TypeDeclaration <$> P.try (parseNonReservedIdent <* lexeme (indented *> P.string "::"))
49+ TypeDeclaration <$> P.try (parseIdent <* lexeme (indented *> P.string "::"))
50 <*> parsePolyType
50 <*> parsePolyType
51
51
52parseTypeSynonymDeclaration :: P.Parsec String ParseState Declaration
52parseTypeSynonymDeclaration :: P.Parsec String ParseState Declaration
@@ -57,7 +57,7 @@ parseTypeSynonymDeclaration =
57
57
58parseValueDeclaration :: P.Parsec String ParseState Declaration
58parseValueDeclaration :: P.Parsec String ParseState Declaration
59parseValueDeclaration =
59parseValueDeclaration =
60− ValueDeclaration <$> parseNonReservedIdent
60+ ValueDeclaration <$> parseIdent
61 <*> P.many parseBinderNoParens
61 <*> P.many parseBinderNoParens
62 <*> P.optionMaybe parseGuard
62 <*> P.optionMaybe parseGuard
63 <*> ((lexeme (indented *> P.char '=')) *> parseValue)
63 <*> ((lexeme (indented *> P.char '=')) *> parseValue)
@@ -66,7 +66,7 @@ parseExternDeclaration :: P.Parsec String ParseState Declaration
66parseExternDeclaration = P.try (reserved "foreign") *> indented *> (reserved "import") *> indented *>
66parseExternDeclaration = P.try (reserved "foreign") *> indented *> (reserved "import") *> indented *>
67 (ExternDataDeclaration <$> (P.try (reserved "data") *> indented *> properName)
67 (ExternDataDeclaration <$> (P.try (reserved "data") *> indented *> properName)
68 <*> (lexeme (indented *> P.string "::") *> parseKind)
68 <*> (lexeme (indented *> P.string "::") *> parseKind)
69− <|> do ident <- parseNonReservedIdent
69+ <|> do ident <- parseIdent
70 js <- P.optionMaybe (parseJSLiteral <$> stringLiteral)
70 js <- P.optionMaybe (parseJSLiteral <$> stringLiteral)
71 ty <- (lexeme (indented *> P.string "::") *> parsePolyType)
71 ty <- (lexeme (indented *> P.string "::") *> parsePolyType)
72 return $ ExternDeclaration (if isJust js then InlineJavascript else ForeignImport) ident js ty)
72 return $ ExternDeclaration (if isJust js then InlineJavascript else ForeignImport) ident js ty)
src/Language/PureScript/Parser/JS.hs+11−4
@@ -22,6 +22,7 @@ import Language.PureScript.Names
22import Language.PureScript.CodeGen.JS.AST
22import Language.PureScript.CodeGen.JS.AST
23import qualified Language.PureScript.Parser.Common as C
23import qualified Language.PureScript.Parser.Common as C
24import Control.Applicative
24import Control.Applicative
25+import Control.Monad
25import Data.Functor.Identity
26import Data.Functor.Identity
26import qualified Text.Parsec as P
27import qualified Text.Parsec as P
27import qualified Text.Parsec.Token as P
28import qualified Text.Parsec.Token as P
@@ -46,14 +47,20 @@ parseObjectLiteral :: P.Parsec String u JS
46parseObjectLiteral = JSObjectLiteral <$> P.braces C.tokenParser (P.commaSep C.tokenParser parseIdentifierAndValue)
47parseObjectLiteral = JSObjectLiteral <$> P.braces C.tokenParser (P.commaSep C.tokenParser parseIdentifierAndValue)
47
48
48parseIdentifierAndValue :: P.Parsec String u (String, JS)
49parseIdentifierAndValue :: P.Parsec String u (String, JS)
49−parseIdentifierAndValue = (,) <$> (C.identifier <* C.colon)
50+parseIdentifierAndValue = (,) <$> (identifier <* C.colon)
50 <*> parseJS
51 <*> parseJS
51
52
53+identifier :: P.Parsec String u String
54+identifier = do
55+ ident <- C.identifier
56+ when (ident `elem` C.reservedJsNames) $ P.unexpected $ ("reserved identifier " ++ show ident)
57+ return ident
58+
52parseFunction :: P.Parsec String u JS
59parseFunction :: P.Parsec String u JS
53parseFunction = do
60parseFunction = do
54 C.reserved "function"
61 C.reserved "function"
55 name <- P.optionMaybe C.identifier
62 name <- P.optionMaybe C.identifier
56− args <- P.parens C.tokenParser $ P.commaSep C.tokenParser C.identifier
63+ args <- P.parens C.tokenParser $ P.commaSep C.tokenParser identifier
57 body <- parseJS
64 body <- parseJS
58 return $ JSFunction name args body
65 return $ JSFunction name args body
59
66
@@ -61,7 +68,7 @@ parseBlock :: P.Parsec String u JS
61parseBlock = JSBlock <$> P.braces C.tokenParser (P.many parseJS)
68parseBlock = JSBlock <$> P.braces C.tokenParser (P.many parseJS)
62
69
63parseVar :: P.Parsec String u JS
70parseVar :: P.Parsec String u JS
64−parseVar = JSVar <$> C.identifier
71+parseVar = JSVar <$> identifier
65
72
66parseJSAtom :: P.Parsec String u JS
73parseJSAtom :: P.Parsec String u JS
67parseJSAtom = P.choice
74parseJSAtom = P.choice
@@ -80,7 +87,7 @@ parseJSAtom = P.choice
80 , P.parens C.tokenParser parseJS ]
87 , P.parens C.tokenParser parseJS ]
81
88
82parseAccessor :: JS -> P.Parsec String u JS
89parseAccessor :: JS -> P.Parsec String u JS
83−parseAccessor js = P.try $ flip JSAccessor js <$> (C.dot *> P.notFollowedBy C.opLetter *> C.identifier)
90+parseAccessor js = P.try $ flip JSAccessor js <$> (C.dot *> P.notFollowedBy C.opLetter *> identifier)
84
91
85parseIndexer :: JS -> P.Parsec String u JS
92parseIndexer :: JS -> P.Parsec String u JS
86parseIndexer js = P.try $ flip JSIndexer js <$> (P.squares C.tokenParser parseJS)
93parseIndexer js = P.try $ flip JSIndexer js <$> (P.squares C.tokenParser parseJS)
src/Language/PureScript/Parser/Types.hs+4−1
@@ -48,7 +48,10 @@ parseObject :: P.Parsec String ParseState Type
48parseObject = braces $ Object <$> parseRow False
48parseObject = braces $ Object <$> parseRow False
49
49
50parseTypeVariable :: P.Parsec String ParseState Type
50parseTypeVariable :: P.Parsec String ParseState Type
51−parseTypeVariable = TypeVar <$> identifier
51+parseTypeVariable = do
52+ ident <- identifier
53+ when (ident `elem` reservedTypeNames) $ P.unexpected $ ident
54+ return $ TypeVar ident
52
55
53parseTypeConstructor :: P.Parsec String ParseState Type
56parseTypeConstructor :: P.Parsec String ParseState Type
54parseTypeConstructor = TypeConstructor <$> parseQualified properName
57parseTypeConstructor = TypeConstructor <$> parseQualified properName
src/Language/PureScript/Parser/Values.hs+2−2
@@ -209,8 +209,8 @@ parseReturn = Return <$> (C.reserved "return" *> parseValue <* C.indented <* C.s
209--
209--
210parseStatement :: P.Parsec String ParseState Statement
210parseStatement :: P.Parsec String ParseState Statement
211parseStatement = P.choice
211parseStatement = P.choice
212− [ parseVariableIntroduction
212+ [ parseAssignment
213− , parseAssignment
213+ , parseVariableIntroduction
214 , parseWhile
214 , parseWhile
215 , parseFor
215 , parseFor
216 , parseIf
216 , parseIf