@@ -18,6 +18,13 @@ module PureScript.Parser.Values (
20import PureScript.Values
20import PureScript.Values
21+import PureScript.Names
22+import PureScript.Declarations
23+import PureScript.Parser.State
24+import Data.Function (on)
26+import Data.Functor.Identity
27+import qualified Data.Map as M
21import qualified PureScript.Parser.Common as C
28import qualified PureScript.Parser.Common as C
22import Control.Applicative
29import Control.Applicative
23import qualified Text.Parsec as P
30import qualified Text.Parsec as P
@@ -27,29 +34,29 @@ import Control.Arrow (Arrow(..))
27import PureScript.Parser.Types
34import PureScript.Parser.Types
28import PureScript.Types
35import PureScript.Types
30−booleanLiteral :: P.Parsec String P.Column Bool
37+booleanLiteral :: P.Parsec String ParseState Bool
31booleanLiteral = (C.reserved "true" >> return True) P.<|> (C.reserved "false" >> return False)
38booleanLiteral = (C.reserved "true" >> return True) P.<|> (C.reserved "false" >> return False)
33−parseNumericLiteral :: P.Parsec String P.Column Value
40+parseNumericLiteral :: P.Parsec String ParseState Value
34parseNumericLiteral = NumericLiteral <$> C.integerOrFloat
41parseNumericLiteral = NumericLiteral <$> C.integerOrFloat
36−parseStringLiteral :: P.Parsec String P.Column Value
43+parseStringLiteral :: P.Parsec String ParseState Value
37parseStringLiteral = StringLiteral <$> C.stringLiteral
44parseStringLiteral = StringLiteral <$> C.stringLiteral
39−parseBooleanLiteral :: P.Parsec String P.Column Value
46+parseBooleanLiteral :: P.Parsec String ParseState Value
40parseBooleanLiteral = BooleanLiteral <$> booleanLiteral
47parseBooleanLiteral = BooleanLiteral <$> booleanLiteral
42−parseArrayLiteral :: P.Parsec String P.Column Value
49+parseArrayLiteral :: P.Parsec String ParseState Value
43parseArrayLiteral = ArrayLiteral <$> (C.squares $ parseValue `P.sepBy` (C.indented *> C.comma))
50parseArrayLiteral = ArrayLiteral <$> (C.squares $ parseValue `P.sepBy` (C.indented *> C.comma))
45−parseObjectLiteral :: P.Parsec String P.Column Value
52+parseObjectLiteral :: P.Parsec String ParseState Value
46parseObjectLiteral = ObjectLiteral <$> (C.braces $ parseIdentifierAndValue `P.sepBy` (C.indented *> C.comma))
53parseObjectLiteral = ObjectLiteral <$> (C.braces $ parseIdentifierAndValue `P.sepBy` (C.indented *> C.comma))
48−parseIdentifierAndValue :: P.Parsec String P.Column (String, Value)
55+parseIdentifierAndValue :: P.Parsec String ParseState (String, Value)
49parseIdentifierAndValue = (,) <$> (C.indented *> C.identifier <* C.indented <* C.colon)
56parseIdentifierAndValue = (,) <$> (C.indented *> C.identifier <* C.indented <* C.colon)
50 <*> (C.indented *> parseValue)
57 <*> (C.indented *> parseValue)
52−parseAbs :: P.Parsec String P.Column Value
59+parseAbs :: P.Parsec String ParseState Value
53parseAbs = do
60parseAbs = do
54 C.lexeme $ P.char '\\'
61 C.lexeme $ P.char '\\'
55 args <- (C.indented *> C.parseIdent) `P.sepBy` (C.indented *> C.comma)
62 args <- (C.indented *> C.parseIdent) `P.sepBy` (C.indented *> C.comma)
@@ -57,35 +64,35 @@ parseAbs = do
57 value <- parseValue
64 value <- parseValue
58 return $ Abs args value
65 return $ Abs args value
60−parseApp :: P.Parsec String P.Column Value
67+parseApp :: P.Parsec String ParseState Value
61parseApp = App <$> parseValue
68parseApp = App <$> parseValue
62 <*> (C.indented *> C.parens (parseValue `P.sepBy` (C.indented *> C.comma)))
69 <*> (C.indented *> C.parens (parseValue `P.sepBy` (C.indented *> C.comma)))
64−parseVar :: P.Parsec String P.Column Value
71+parseVar :: P.Parsec String ParseState Value
65parseVar = Var <$> C.parseIdent
72parseVar = Var <$> C.parseIdent
67−parseConstructor :: P.Parsec String P.Column Value
74+parseConstructor :: P.Parsec String ParseState Value
68parseConstructor = Constructor <$> C.properName
75parseConstructor = Constructor <$> C.properName
70−parseCase :: P.Parsec String P.Column Value
77+parseCase :: P.Parsec String ParseState Value
71parseCase = Case <$> (P.between (C.reserved "case") (C.indented *> C.reserved "of") parseValue)
78parseCase = Case <$> (P.between (C.reserved "case") (C.indented *> C.reserved "of") parseValue)
72 <*> (C.indented *> C.mark (P.many (C.same *> C.mark parseCaseAlternative)))
79 <*> (C.indented *> C.mark (P.many (C.same *> C.mark parseCaseAlternative)))
74−parseCaseAlternative :: P.Parsec String P.Column (Binder, Value)
81+parseCaseAlternative :: P.Parsec String ParseState (Binder, Value)
75parseCaseAlternative = (,) <$> (parseGuardedBinder <* C.lexeme (P.string "->")) <*> parseValue
82parseCaseAlternative = (,) <$> (parseGuardedBinder <* C.lexeme (P.string "->")) <*> parseValue
77−parseIfThenElse :: P.Parsec String P.Column Value
84+parseIfThenElse :: P.Parsec String ParseState Value
78parseIfThenElse = IfThenElse <$> (C.reserved "if" *> C.indented *> parseValue)
85parseIfThenElse = IfThenElse <$> (C.reserved "if" *> C.indented *> parseValue)
79 <*> (C.indented *> C.reserved "then" *> C.indented *> parseValue)
86 <*> (C.indented *> C.reserved "then" *> C.indented *> parseValue)
80 <*> (C.indented *> C.reserved "else" *> C.indented *> parseValue)
87 <*> (C.indented *> C.reserved "else" *> C.indented *> parseValue)
82−parseBlock :: P.Parsec String P.Column Value
89+parseBlock :: P.Parsec String ParseState Value
83parseBlock = Block <$> (C.reserved "do" *> parseManyStatements)
90parseBlock = Block <$> (C.reserved "do" *> parseManyStatements)
85−parseManyStatements :: P.Parsec String P.Column [Statement]
92+parseManyStatements :: P.Parsec String ParseState [Statement]
86parseManyStatements = C.indented *> (C.mark $ P.many $ C.same *> C.mark parseStatement)
93parseManyStatements = C.indented *> (C.mark $ P.many $ C.same *> C.mark parseStatement)
88−parseValueAtom :: P.Parsec String P.Column Value
95+parseValueAtom :: P.Parsec String ParseState Value
89parseValueAtom = C.indented *> P.choice (map P.try
96parseValueAtom = C.indented *> P.choice (map P.try
90 [ parseNumericLiteral
97 [ parseNumericLiteral
91 , parseStringLiteral
98 , parseStringLiteral
@@ -100,8 +107,10 @@ parseValueAtom = C.indented *> P.choice (map P.try
100 , parseIfThenElse
107 , parseIfThenElse
101 , C.parens parseValue ])
108 , C.parens parseValue ])
103−parseValue :: P.Parsec String P.Column Value
110+parseValue :: P.Parsec String ParseState Value
112+ customOps <- fixities <$> P.getState
104−parseValue = buildExpressionParser operators . C.buildPostfixParser postfixTable2 $ indexersAndAccessors
113+ buildExpressionParser (operators customOps) . C.buildPostfixParser postfixTable2 $ indexersAndAccessors
106 indexersAndAccessors = C.buildPostfixParser postfixTable1 $ parseValueAtom
115 indexersAndAccessors = C.buildPostfixParser postfixTable1 $ parseValueAtom
107 postfixTable1 = [ Accessor <$> (C.indented *> C.dot *> C.indented *> C.identifier)
116 postfixTable1 = [ Accessor <$> (C.indented *> C.dot *> C.indented *> C.identifier)
@@ -109,11 +118,13 @@ parseValue = buildExpressionParser operators . C.buildPostfixParser postfixTable
109 postfixTable2 = [ C.indented *> indexersAndAccessors >>= \t2 -> return (\t1 -> App t1 [t2])
118 postfixTable2 = [ C.indented *> indexersAndAccessors >>= \t2 -> return (\t1 -> App t1 [t2])
110 , flip App <$> (C.indented *> C.parens (parseValue `P.sepBy` (C.indented *> C.comma)))
119 , flip App <$> (C.indented *> C.parens (parseValue `P.sepBy` (C.indented *> C.comma)))
111 , flip TypedValue <$> (P.try $ C.lexeme (C.indented *> P.string "::") *> parsePolyType) ]
120 , flip TypedValue <$> (P.try $ C.lexeme (C.indented *> P.string "::") *> parsePolyType) ]
112− operators = [ [ Prefix $ C.lexeme (P.try $ C.indented *> C.reservedOp "!") >> return (Unary Not)
122+ [ [ Prefix $ C.lexeme (P.try $ C.indented *> C.reservedOp "!") >> return (Unary Not)
113 , Prefix $ C.lexeme (P.try $ C.indented *> C.reservedOp "~") >> return (Unary BitwiseNot)
123 , Prefix $ C.lexeme (P.try $ C.indented *> C.reservedOp "~") >> return (Unary BitwiseNot)
114 , Prefix $ C.lexeme (P.try $ C.indented *> C.reservedOp "-") >> return (Unary Negate)
124 , Prefix $ C.lexeme (P.try $ C.indented *> C.reservedOp "-") >> return (Unary Negate)
115 , Prefix $ C.lexeme (P.try $ C.indented *> C.reservedOp "+") >> return id ]
125 , Prefix $ C.lexeme (P.try $ C.indented *> C.reservedOp "+") >> return id ]
126+ ] ++ customOperatorTable user ++
116− , [ Infix (C.lexeme (P.try (C.indented *> C.parseIdentInfix) >>= \ident -> return $ \t1 t2 -> App (App (Var ident) [t1]) [t2])) AssocRight ]
127+ [ [ Infix (C.lexeme (P.try (C.indented *> C.parseIdentInfix) >>= \ident -> return $ \t1 t2 -> App (App (Var ident) [t1]) [t2])) AssocRight ]
117 , [ Infix (C.lexeme (P.try $ C.indented *> C.reservedOp "<=") >> return (Binary LessThanOrEqualTo)) AssocRight
128 , [ Infix (C.lexeme (P.try $ C.indented *> C.reservedOp "<=") >> return (Binary LessThanOrEqualTo)) AssocRight
118 , Infix (C.lexeme (P.try $ C.indented *> C.reservedOp ">=") >> return (Binary GreaterThanOrEqualTo)) AssocRight ]
129 , Infix (C.lexeme (P.try $ C.indented *> C.reservedOp ">=") >> return (Binary GreaterThanOrEqualTo)) AssocRight ]
119 , [ Infix (C.lexeme (P.try $ C.indented *> C.reservedOp "<") >> return (Binary LessThan)) AssocRight
130 , [ Infix (C.lexeme (P.try $ C.indented *> C.reservedOp "<") >> return (Binary LessThan)) AssocRight
@@ -136,7 +147,24 @@ parseValue = buildExpressionParser operators . C.buildPostfixParser postfixTable
136 , [ Infix (C.lexeme (P.try $ C.indented *> C.reservedOp "||") >> return (Binary Or)) AssocRight ]
147 , [ Infix (C.lexeme (P.try $ C.indented *> C.reservedOp "||") >> return (Binary Or)) AssocRight ]
150+customOperatorTable :: M.Map String Fixity -> OperatorTable String ParseState Identity Value
151+customOperatorTable fixities =
153+ ops = map (\(name, Fixity a p) -> (name, (a, p))) . M.toList $ fixities
154+ sorted = sortBy (compare `on` (snd . snd)) ops
155+ levels = groupBy ((==) `on` (snd . snd)) sorted
157+ flip map levels (map (\(name, (a, _)) -> flip Infix (toAssoc a) $ do
158+ C.lexeme $ P.try $ do
161+ return $ \t1 t2 -> App (App (Var (Op name)) [t1]) [t2]))
163+toAssoc :: Associativity -> Assoc
164+toAssoc Infixl = AssocLeft
165+toAssoc Infixr = AssocRight
139−parseVariableIntroduction :: P.Parsec String P.Column Statement
167+parseVariableIntroduction :: P.Parsec String ParseState Statement
140parseVariableIntroduction = do
168parseVariableIntroduction = do
141 C.reserved "var"
169 C.reserved "var"
142 name <- C.indented *> C.parseIdent
170 name <- C.indented *> C.parseIdent
@@ -144,45 +172,45 @@ parseVariableIntroduction = do
144 value <- parseValue
172 value <- parseValue
145 return $ VariableIntroduction name value
173 return $ VariableIntroduction name value
147−parseAssignment :: P.Parsec String P.Column Statement
175+parseAssignment :: P.Parsec String ParseState Statement
148parseAssignment = do
176parseAssignment = do
149 tgt <- parseAssignmentTarget
177 tgt <- parseAssignmentTarget
150 C.lexeme $ C.indented *> P.char '='
178 C.lexeme $ C.indented *> P.char '='
151 value <- parseValue
179 value <- parseValue
152 return $ Assignment tgt value
180 return $ Assignment tgt value
154−parseWhile :: P.Parsec String P.Column Statement
182+parseWhile :: P.Parsec String ParseState Statement
155parseWhile = While <$> (C.reserved "while" *> C.indented *> parseValue <* C.indented <* C.colon)
183parseWhile = While <$> (C.reserved "while" *> C.indented *> parseValue <* C.indented <* C.colon)
156 <*> parseManyStatements
184 <*> parseManyStatements
158−parseFor :: P.Parsec String P.Column Statement
186+parseFor :: P.Parsec String ParseState Statement
159parseFor = For <$> (C.reserved "for" *> C.indented *> C.parseIdent)
187parseFor = For <$> (C.reserved "for" *> C.indented *> C.parseIdent)
160 <*> (C.indented *> C.lexeme (P.string "<-") *> parseValue)
188 <*> (C.indented *> C.lexeme (P.string "<-") *> parseValue)
161 <*> (C.indented *> C.reserved "until" *> parseValue <* C.colon)
189 <*> (C.indented *> C.reserved "until" *> parseValue <* C.colon)
162 <*> parseManyStatements
190 <*> parseManyStatements
164−parseForEach :: P.Parsec String P.Column Statement
192+parseForEach :: P.Parsec String ParseState Statement
165parseForEach = ForEach <$> (C.reserved "foreach" *> C.indented *> C.parseIdent)
193parseForEach = ForEach <$> (C.reserved "foreach" *> C.indented *> C.parseIdent)
166 <*> (C.indented *> C.reserved "in" *> parseValue <* C.colon)
194 <*> (C.indented *> C.reserved "in" *> parseValue <* C.colon)
167 <*> parseManyStatements
195 <*> parseManyStatements
169−parseIf :: P.Parsec String P.Column Statement
197+parseIf :: P.Parsec String ParseState Statement
170parseIf = If <$> parseIfStatement
198parseIf = If <$> parseIfStatement
172−parseIfStatement :: P.Parsec String P.Column IfStatement
200+parseIfStatement :: P.Parsec String ParseState IfStatement
173parseIfStatement =
201parseIfStatement =
174 IfStatement <$> (C.reserved "if" *> C.indented *> parseValue <* C.indented <* C.colon)
202 IfStatement <$> (C.reserved "if" *> C.indented *> parseValue <* C.indented <* C.colon)
175 <*> parseManyStatements
203 <*> parseManyStatements
176 <*> P.optionMaybe (C.same *> parseElseStatement)
204 <*> P.optionMaybe (C.same *> parseElseStatement)
178−parseElseStatement :: P.Parsec String P.Column ElseStatement
206+parseElseStatement :: P.Parsec String ParseState ElseStatement
179parseElseStatement = C.reserved "else" >> (ElseIf <$> (C.indented *> parseIfStatement)
207parseElseStatement = C.reserved "else" >> (ElseIf <$> (C.indented *> parseIfStatement)
180 <|> Else <$> (C.indented *> C.colon *> parseManyStatements))
208 <|> Else <$> (C.indented *> C.colon *> parseManyStatements))
182−parseReturn :: P.Parsec String P.Column Statement
210+parseReturn :: P.Parsec String ParseState Statement
183parseReturn = Return <$> (C.reserved "return" *> parseValue)
211parseReturn = Return <$> (C.reserved "return" *> parseValue)
185−parseStatement :: P.Parsec String P.Column Statement
213+parseStatement :: P.Parsec String ParseState Statement
186parseStatement = P.choice (map P.try
214parseStatement = P.choice (map P.try
187 [ parseVariableIntroduction
215 [ parseVariableIntroduction
188 , parseAssignment
216 , parseAssignment
@@ -192,46 +220,46 @@ parseStatement = P.choice (map P.try
192 , parseIf
220 , parseIf
193 , parseReturn ])
221 , parseReturn ])
195−parseStringBinder :: P.Parsec String P.Column Binder
223+parseStringBinder :: P.Parsec String ParseState Binder
196parseStringBinder = StringBinder <$> C.stringLiteral
224parseStringBinder = StringBinder <$> C.stringLiteral
198−parseBooleanBinder :: P.Parsec String P.Column Binder
226+parseBooleanBinder :: P.Parsec String ParseState Binder
199parseBooleanBinder = BooleanBinder <$> booleanLiteral
227parseBooleanBinder = BooleanBinder <$> booleanLiteral
201−parseNumberBinder :: P.Parsec String P.Column Binder
229+parseNumberBinder :: P.Parsec String ParseState Binder
202parseNumberBinder = NumberBinder <$> C.integerOrFloat
230parseNumberBinder = NumberBinder <$> C.integerOrFloat
204−parseVarBinder :: P.Parsec String P.Column Binder
232+parseVarBinder :: P.Parsec String ParseState Binder
205parseVarBinder = VarBinder <$> C.parseIdent
233parseVarBinder = VarBinder <$> C.parseIdent
207−parseNullaryBinder :: P.Parsec String P.Column Binder
235+parseNullaryBinder :: P.Parsec String ParseState Binder
208parseNullaryBinder = NullaryBinder <$> C.lexeme C.properName
236parseNullaryBinder = NullaryBinder <$> C.lexeme C.properName
210−parseUnaryBinder :: P.Parsec String P.Column Binder
238+parseUnaryBinder :: P.Parsec String ParseState Binder
211parseUnaryBinder = UnaryBinder <$> C.lexeme C.properName <*> (C.indented *> parseBinder)
239parseUnaryBinder = UnaryBinder <$> C.lexeme C.properName <*> (C.indented *> parseBinder)
213−parseObjectBinder :: P.Parsec String P.Column Binder
241+parseObjectBinder :: P.Parsec String ParseState Binder
214parseObjectBinder = ObjectBinder <$> C.braces ((C.indented *> parseIdentifierAndBinder) `P.sepBy` (C.indented *> C.comma))
242parseObjectBinder = ObjectBinder <$> C.braces ((C.indented *> parseIdentifierAndBinder) `P.sepBy` (C.indented *> C.comma))
216−parseArrayBinder :: P.Parsec String P.Column Binder
244+parseArrayBinder :: P.Parsec String ParseState Binder
217parseArrayBinder = C.squares $ ArrayBinder <$> ((C.indented *> parseBinder) `P.sepBy` (C.indented *> C.comma))
245parseArrayBinder = C.squares $ ArrayBinder <$> ((C.indented *> parseBinder) `P.sepBy` (C.indented *> C.comma))
218 <*> P.optionMaybe (C.indented *> C.colon *> C.indented *> parseBinder)
246 <*> P.optionMaybe (C.indented *> C.colon *> C.indented *> parseBinder)
220−parseNamedBinder :: P.Parsec String P.Column Binder
248+parseNamedBinder :: P.Parsec String ParseState Binder
221parseNamedBinder = NamedBinder <$> (C.parseIdent <* C.indented <* C.lexeme (P.char '@'))
249parseNamedBinder = NamedBinder <$> (C.parseIdent <* C.indented <* C.lexeme (P.char '@'))
222 <*> (C.indented *> parseBinder)
250 <*> (C.indented *> parseBinder)
224−parseNullBinder :: P.Parsec String P.Column Binder
252+parseNullBinder :: P.Parsec String ParseState Binder
225parseNullBinder = C.lexeme (P.char '_') *> P.notFollowedBy C.identLetter *> return NullBinder
253parseNullBinder = C.lexeme (P.char '_') *> P.notFollowedBy C.identLetter *> return NullBinder
227−parseIdentifierAndBinder :: P.Parsec String P.Column (String, Binder)
255+parseIdentifierAndBinder :: P.Parsec String ParseState (String, Binder)
228parseIdentifierAndBinder = do
256parseIdentifierAndBinder = do
229 name <- C.lexeme C.identifier
257 name <- C.lexeme C.identifier
230 C.lexeme $ C.indented *> P.char '='
258 C.lexeme $ C.indented *> P.char '='
231 binder <- C.indented *> parseBinder
259 binder <- C.indented *> parseBinder
232 return (name, binder)
260 return (name, binder)
234−parseBinder :: P.Parsec String P.Column Binder
262+parseBinder :: P.Parsec String ParseState Binder
235parseBinder = P.choice (map P.try
263parseBinder = P.choice (map P.try
236 [ parseNullBinder
264 [ parseNullBinder
237 , parseStringBinder
265 , parseStringBinder
@@ -245,10 +273,10 @@ parseBinder = P.choice (map P.try
245 , parseArrayBinder
273 , parseArrayBinder
246 , C.parens parseBinder ])
274 , C.parens parseBinder ])
248−parseGuardedBinder :: P.Parsec String P.Column Binder
276+parseGuardedBinder :: P.Parsec String ParseState Binder
249parseGuardedBinder = flip ($) <$> parseBinder <*> P.option id (GuardedBinder <$> (C.indented *> C.lexeme (P.char '|') *> C.indented *> parseValue))
277parseGuardedBinder = flip ($) <$> parseBinder <*> P.option id (GuardedBinder <$> (C.indented *> C.lexeme (P.char '|') *> C.indented *> parseValue))
251−parseAssignmentTarget :: P.Parsec String P.Column AssignmentTarget
279+parseAssignmentTarget :: P.Parsec String ParseState AssignmentTarget
252parseAssignmentTarget = buildExpressionParser operators (AssignVariable <$> C.parseIdent)
280parseAssignmentTarget = buildExpressionParser operators (AssignVariable <$> C.parseIdent)
254 operators = [ [ Postfix $ AssignArrayIndex <$> (C.indented *> C.squares parseValue)
282 operators = [ [ Postfix $ AssignArrayIndex <$> (C.indented *> C.squares parseValue)