@@ -18,6 +18,13 @@ module PureScript.Parser.Values (
1818) where
1919
2020import PureScript.Values
21+import PureScript.Names
22+import PureScript.Declarations
23+import PureScript.Parser.State
24+import Data.Function (on)
25+import Data.List
26+import Data.Functor.Identity
27+import qualified Data.Map as M
2128import qualified PureScript.Parser.Common as C
2229import Control.Applicative
2330import qualified Text.Parsec as P
@@ -27,29 +34,29 @@ import Control.Arrow (Arrow(..))
2734import PureScript.Parser.Types
2835import PureScript.Types
2936
30−booleanLiteral :: P.Parsec String P.Column Bool
37+booleanLiteral :: P.Parsec String ParseState Bool
3138booleanLiteral = (C.reserved "true" >> return True) P.<|> (C.reserved "false" >> return False)
3239
33−parseNumericLiteral :: P.Parsec String P.Column Value
40+parseNumericLiteral :: P.Parsec String ParseState Value
3441parseNumericLiteral = NumericLiteral <$> C.integerOrFloat
3542
36−parseStringLiteral :: P.Parsec String P.Column Value
43+parseStringLiteral :: P.Parsec String ParseState Value
3744parseStringLiteral = StringLiteral <$> C.stringLiteral
3845
39−parseBooleanLiteral :: P.Parsec String P.Column Value
46+parseBooleanLiteral :: P.Parsec String ParseState Value
4047parseBooleanLiteral = BooleanLiteral <$> booleanLiteral
4148
42−parseArrayLiteral :: P.Parsec String P.Column Value
49+parseArrayLiteral :: P.Parsec String ParseState Value
4350parseArrayLiteral = ArrayLiteral <$> (C.squares $ parseValue `P.sepBy` (C.indented *> C.comma))
4451
45−parseObjectLiteral :: P.Parsec String P.Column Value
52+parseObjectLiteral :: P.Parsec String ParseState Value
4653parseObjectLiteral = ObjectLiteral <$> (C.braces $ parseIdentifierAndValue `P.sepBy` (C.indented *> C.comma))
4754
48−parseIdentifierAndValue :: P.Parsec String P.Column (String, Value)
55+parseIdentifierAndValue :: P.Parsec String ParseState (String, Value)
4956parseIdentifierAndValue = (,) <$> (C.indented *> C.identifier <* C.indented <* C.colon)
5057 <*> (C.indented *> parseValue)
5158
52−parseAbs :: P.Parsec String P.Column Value
59+parseAbs :: P.Parsec String ParseState Value
5360parseAbs = do
5461 C.lexeme $ P.char '\\'
5562 args <- (C.indented *> C.parseIdent) `P.sepBy` (C.indented *> C.comma)
@@ -57,35 +64,35 @@ parseAbs = do
5764 value <- parseValue
5865 return $ Abs args value
5966
60−parseApp :: P.Parsec String P.Column Value
67+parseApp :: P.Parsec String ParseState Value
6168parseApp = App <$> parseValue
6269 <*> (C.indented *> C.parens (parseValue `P.sepBy` (C.indented *> C.comma)))
6370
64−parseVar :: P.Parsec String P.Column Value
71+parseVar :: P.Parsec String ParseState Value
6572parseVar = Var <$> C.parseIdent
6673
67−parseConstructor :: P.Parsec String P.Column Value
74+parseConstructor :: P.Parsec String ParseState Value
6875parseConstructor = Constructor <$> C.properName
6976
70−parseCase :: P.Parsec String P.Column Value
77+parseCase :: P.Parsec String ParseState Value
7178parseCase = Case <$> (P.between (C.reserved "case") (C.indented *> C.reserved "of") parseValue)
7279 <*> (C.indented *> C.mark (P.many (C.same *> C.mark parseCaseAlternative)))
7380
74−parseCaseAlternative :: P.Parsec String P.Column (Binder, Value)
81+parseCaseAlternative :: P.Parsec String ParseState (Binder, Value)
7582parseCaseAlternative = (,) <$> (parseGuardedBinder <* C.lexeme (P.string "->")) <*> parseValue
7683
77−parseIfThenElse :: P.Parsec String P.Column Value
84+parseIfThenElse :: P.Parsec String ParseState Value
7885parseIfThenElse = IfThenElse <$> (C.reserved "if" *> C.indented *> parseValue)
7986 <*> (C.indented *> C.reserved "then" *> C.indented *> parseValue)
8087 <*> (C.indented *> C.reserved "else" *> C.indented *> parseValue)
81−
82−parseBlock :: P.Parsec String P.Column Value
88+
89+parseBlock :: P.Parsec String ParseState Value
8390parseBlock = Block <$> (C.reserved "do" *> parseManyStatements)
8491
85−parseManyStatements :: P.Parsec String P.Column [Statement]
92+parseManyStatements :: P.Parsec String ParseState [Statement]
8693parseManyStatements = C.indented *> (C.mark $ P.many $ C.same *> C.mark parseStatement)
8794
88−parseValueAtom :: P.Parsec String P.Column Value
95+parseValueAtom :: P.Parsec String ParseState Value
8996parseValueAtom = C.indented *> P.choice (map P.try
9097 [ parseNumericLiteral
9198 , parseStringLiteral
@@ -100,8 +107,10 @@ parseValueAtom = C.indented *> P.choice (map P.try
100107 , parseIfThenElse
101108 , C.parens parseValue ])
102109
103−parseValue :: P.Parsec String P.Column Value
104−parseValue = buildExpressionParser operators . C.buildPostfixParser postfixTable2 $ indexersAndAccessors
110+parseValue :: P.Parsec String ParseState Value
111+parseValue = do
112+ customOps <- fixities <$> P.getState
113+ buildExpressionParser (operators customOps) . C.buildPostfixParser postfixTable2 $ indexersAndAccessors
105114 where
106115 indexersAndAccessors = C.buildPostfixParser postfixTable1 $ parseValueAtom
107116 postfixTable1 = [ Accessor <$> (C.indented *> C.dot *> C.indented *> C.identifier)
@@ -109,11 +118,13 @@ parseValue = buildExpressionParser operators . C.buildPostfixParser postfixTable
109118 postfixTable2 = [ C.indented *> indexersAndAccessors >>= \t2 -> return (\t1 -> App t1 [t2])
110119 , flip App <$> (C.indented *> C.parens (parseValue `P.sepBy` (C.indented *> C.comma)))
111120 , 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)
121+ operators user =
122+ [ [ Prefix $ C.lexeme (P.try $ C.indented *> C.reservedOp "!") >> return (Unary Not)
113123 , Prefix $ C.lexeme (P.try $ C.indented *> C.reservedOp "~") >> return (Unary BitwiseNot)
114124 , Prefix $ C.lexeme (P.try $ C.indented *> C.reservedOp "-") >> return (Unary Negate)
115125 , Prefix $ C.lexeme (P.try $ C.indented *> C.reservedOp "+") >> return id ]
116− , [ Infix (C.lexeme (P.try (C.indented *> C.parseIdentInfix) >>= \ident -> return $ \t1 t2 -> App (App (Var ident) [t1]) [t2])) AssocRight ]
126+ ] ++ customOperatorTable user ++
127+ [ [ Infix (C.lexeme (P.try (C.indented *> C.parseIdentInfix) >>= \ident -> return $ \t1 t2 -> App (App (Var ident) [t1]) [t2])) AssocRight ]
117128 , [ Infix (C.lexeme (P.try $ C.indented *> C.reservedOp "<=") >> return (Binary LessThanOrEqualTo)) AssocRight
118129 , Infix (C.lexeme (P.try $ C.indented *> C.reservedOp ">=") >> return (Binary GreaterThanOrEqualTo)) AssocRight ]
119130 , [ Infix (C.lexeme (P.try $ C.indented *> C.reservedOp "<") >> return (Binary LessThan)) AssocRight
@@ -136,7 +147,24 @@ parseValue = buildExpressionParser operators . C.buildPostfixParser postfixTable
136147 , [ Infix (C.lexeme (P.try $ C.indented *> C.reservedOp "||") >> return (Binary Or)) AssocRight ]
137148 ]
138149
139−parseVariableIntroduction :: P.Parsec String P.Column Statement
150+customOperatorTable :: M.Map String Fixity -> OperatorTable String ParseState Identity Value
151+customOperatorTable fixities =
152+ let
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
156+ in
157+ flip map levels (map (\(name, (a, _)) -> flip Infix (toAssoc a) $ do
158+ C.lexeme $ P.try $ do
159+ C.indented
160+ C.reservedOp name
161+ return $ \t1 t2 -> App (App (Var (Op name)) [t1]) [t2]))
162+
163+toAssoc :: Associativity -> Assoc
164+toAssoc Infixl = AssocLeft
165+toAssoc Infixr = AssocRight
166+
167+parseVariableIntroduction :: P.Parsec String ParseState Statement
140168parseVariableIntroduction = do
141169 C.reserved "var"
142170 name <- C.indented *> C.parseIdent
@@ -144,45 +172,45 @@ parseVariableIntroduction = do
144172 value <- parseValue
145173 return $ VariableIntroduction name value
146174
147−parseAssignment :: P.Parsec String P.Column Statement
175+parseAssignment :: P.Parsec String ParseState Statement
148176parseAssignment = do
149177 tgt <- parseAssignmentTarget
150178 C.lexeme $ C.indented *> P.char '='
151179 value <- parseValue
152180 return $ Assignment tgt value
153181
154−parseWhile :: P.Parsec String P.Column Statement
182+parseWhile :: P.Parsec String ParseState Statement
155183parseWhile = While <$> (C.reserved "while" *> C.indented *> parseValue <* C.indented <* C.colon)
156184 <*> parseManyStatements
157185
158−parseFor :: P.Parsec String P.Column Statement
186+parseFor :: P.Parsec String ParseState Statement
159187parseFor = For <$> (C.reserved "for" *> C.indented *> C.parseIdent)
160188 <*> (C.indented *> C.lexeme (P.string "<-") *> parseValue)
161189 <*> (C.indented *> C.reserved "until" *> parseValue <* C.colon)
162190 <*> parseManyStatements
163191
164−parseForEach :: P.Parsec String P.Column Statement
192+parseForEach :: P.Parsec String ParseState Statement
165193parseForEach = ForEach <$> (C.reserved "foreach" *> C.indented *> C.parseIdent)
166194 <*> (C.indented *> C.reserved "in" *> parseValue <* C.colon)
167195 <*> parseManyStatements
168196
169−parseIf :: P.Parsec String P.Column Statement
197+parseIf :: P.Parsec String ParseState Statement
170198parseIf = If <$> parseIfStatement
171199
172−parseIfStatement :: P.Parsec String P.Column IfStatement
200+parseIfStatement :: P.Parsec String ParseState IfStatement
173201parseIfStatement =
174202 IfStatement <$> (C.reserved "if" *> C.indented *> parseValue <* C.indented <* C.colon)
175203 <*> parseManyStatements
176204 <*> P.optionMaybe (C.same *> parseElseStatement)
177205
178−parseElseStatement :: P.Parsec String P.Column ElseStatement
206+parseElseStatement :: P.Parsec String ParseState ElseStatement
179207parseElseStatement = C.reserved "else" >> (ElseIf <$> (C.indented *> parseIfStatement)
180208 <|> Else <$> (C.indented *> C.colon *> parseManyStatements))
181209
182−parseReturn :: P.Parsec String P.Column Statement
210+parseReturn :: P.Parsec String ParseState Statement
183211parseReturn = Return <$> (C.reserved "return" *> parseValue)
184212
185−parseStatement :: P.Parsec String P.Column Statement
213+parseStatement :: P.Parsec String ParseState Statement
186214parseStatement = P.choice (map P.try
187215 [ parseVariableIntroduction
188216 , parseAssignment
@@ -192,46 +220,46 @@ parseStatement = P.choice (map P.try
192220 , parseIf
193221 , parseReturn ])
194222
195−parseStringBinder :: P.Parsec String P.Column Binder
223+parseStringBinder :: P.Parsec String ParseState Binder
196224parseStringBinder = StringBinder <$> C.stringLiteral
197225
198−parseBooleanBinder :: P.Parsec String P.Column Binder
226+parseBooleanBinder :: P.Parsec String ParseState Binder
199227parseBooleanBinder = BooleanBinder <$> booleanLiteral
200228
201−parseNumberBinder :: P.Parsec String P.Column Binder
229+parseNumberBinder :: P.Parsec String ParseState Binder
202230parseNumberBinder = NumberBinder <$> C.integerOrFloat
203231
204−parseVarBinder :: P.Parsec String P.Column Binder
232+parseVarBinder :: P.Parsec String ParseState Binder
205233parseVarBinder = VarBinder <$> C.parseIdent
206234
207−parseNullaryBinder :: P.Parsec String P.Column Binder
235+parseNullaryBinder :: P.Parsec String ParseState Binder
208236parseNullaryBinder = NullaryBinder <$> C.lexeme C.properName
209237
210−parseUnaryBinder :: P.Parsec String P.Column Binder
238+parseUnaryBinder :: P.Parsec String ParseState Binder
211239parseUnaryBinder = UnaryBinder <$> C.lexeme C.properName <*> (C.indented *> parseBinder)
212240
213−parseObjectBinder :: P.Parsec String P.Column Binder
241+parseObjectBinder :: P.Parsec String ParseState Binder
214242parseObjectBinder = ObjectBinder <$> C.braces ((C.indented *> parseIdentifierAndBinder) `P.sepBy` (C.indented *> C.comma))
215243
216−parseArrayBinder :: P.Parsec String P.Column Binder
244+parseArrayBinder :: P.Parsec String ParseState Binder
217245parseArrayBinder = C.squares $ ArrayBinder <$> ((C.indented *> parseBinder) `P.sepBy` (C.indented *> C.comma))
218246 <*> P.optionMaybe (C.indented *> C.colon *> C.indented *> parseBinder)
219247
220−parseNamedBinder :: P.Parsec String P.Column Binder
248+parseNamedBinder :: P.Parsec String ParseState Binder
221249parseNamedBinder = NamedBinder <$> (C.parseIdent <* C.indented <* C.lexeme (P.char '@'))
222250 <*> (C.indented *> parseBinder)
223251
224−parseNullBinder :: P.Parsec String P.Column Binder
252+parseNullBinder :: P.Parsec String ParseState Binder
225253parseNullBinder = C.lexeme (P.char '_') *> P.notFollowedBy C.identLetter *> return NullBinder
226254
227−parseIdentifierAndBinder :: P.Parsec String P.Column (String, Binder)
255+parseIdentifierAndBinder :: P.Parsec String ParseState (String, Binder)
228256parseIdentifierAndBinder = do
229257 name <- C.lexeme C.identifier
230258 C.lexeme $ C.indented *> P.char '='
231259 binder <- C.indented *> parseBinder
232260 return (name, binder)
233261
234−parseBinder :: P.Parsec String P.Column Binder
262+parseBinder :: P.Parsec String ParseState Binder
235263parseBinder = P.choice (map P.try
236264 [ parseNullBinder
237265 , parseStringBinder
@@ -245,10 +273,10 @@ parseBinder = P.choice (map P.try
245273 , parseArrayBinder
246274 , C.parens parseBinder ])
247275
248−parseGuardedBinder :: P.Parsec String P.Column Binder
276+parseGuardedBinder :: P.Parsec String ParseState Binder
249277parseGuardedBinder = flip ($) <$> parseBinder <*> P.option id (GuardedBinder <$> (C.indented *> C.lexeme (P.char '|') *> C.indented *> parseValue))
250278
251−parseAssignmentTarget :: P.Parsec String P.Column AssignmentTarget
279+parseAssignmentTarget :: P.Parsec String ParseState AssignmentTarget
252280parseAssignmentTarget = buildExpressionParser operators (AssignVariable <$> C.parseIdent)
253281 where
254282 operators = [ [ Postfix $ AssignArrayIndex <$> (C.indented *> C.squares parseValue)