@@ -22,6 +22,7 @@ import qualified PureScript.Parser.Common as C
2222import Control.Applicative
2323import qualified Text.Parsec as P
2424import Text.Parsec.Expr
25+import Control.Monad
2526import Control.Arrow (Arrow(..))
2627import PureScript.Parser.Types
2728import PureScript.Types
@@ -74,7 +75,7 @@ parseCaseAlternative :: P.Parsec String () (Binder, Value)
7475parseCaseAlternative = (,) <$> (parseBinder <* C.lexeme (P.string "->")) <*> parseValue
7576
7677parseBlock :: P.Parsec String () Value
77−parseBlock = Block <$> (C.braces $ P.many parseStatement)
78+parseBlock = Block <$> (C.braces $ P.many (parseStatement True))
7879
7980parseValueAtom :: P.Parsec String () Value
8081parseValueAtom = P.choice $ map P.try
@@ -100,7 +101,10 @@ parseValue = buildExpressionParser operators $ C.fold (C.lexeme typedValue) (C.l
100101 , [ Prefix $ C.lexeme (P.char '!') >> return (Unary Not)
101102 , Prefix $ C.lexeme (P.char '~') >> return (Unary BitwiseNot)
102103 , Prefix $ C.lexeme (P.char '-') >> return (Unary Negate) ]
103− , [ Infix (C.lexeme (P.char '*') >> return (Binary Multiply)) AssocRight
104+ , [ Infix (C.lexeme (P.try (P.string "<=")) >> return (Binary LessThanOrEqualTo)) AssocRight
105+ , Infix (C.lexeme (P.try (P.string ">=")) >> return (Binary GreaterThanOrEqualTo)) AssocRight
106+ , Infix (C.lexeme (P.try (P.char '<' <* P.notFollowedBy (P.char '<'))) >> return (Binary LessThan)) AssocRight ]
107+ , [ Infix (C.lexeme (P.try (P.char '>' <* P.notFollowedBy (P.char '>'))) >> return (Binary GreaterThan)) AssocRight
104108 , Infix (C.lexeme (P.char '/') >> return (Binary Divide)) AssocRight
105109 , Infix (C.lexeme (P.char '%') >> return (Binary Modulus)) AssocRight ]
106110 , [ Infix (C.lexeme (P.try (P.string "++")) >> return (Binary Concat)) AssocRight
@@ -118,25 +122,25 @@ parseValue = buildExpressionParser operators $ C.fold (C.lexeme typedValue) (C.l
118122 , [ Infix (C.lexeme (P.string "||") >> return (Binary Or)) AssocRight ]
119123 ]
120124
121−parseVariableIntroduction :: P.Parsec String () Statement
122−parseVariableIntroduction = do
125+parseVariableIntroduction :: Bool -> P.Parsec String () Statement
126+parseVariableIntroduction requireSemi = do
123127 C.reserved "var"
124128 name <- C.identifier
125129 C.lexeme $ P.char '='
126130 value <- parseValue
127− C.semi
131+ when requireSemi (void C.semi)
128132 return $ VariableIntroduction name value
129133
130−parseAssignment :: P.Parsec String () (Statement)
131−parseAssignment = do
132− tgt <- C.identifier
134+parseAssignment :: Bool -> P.Parsec String () (Statement)
135+parseAssignment requireSemi = do
136+ tgt <- parseAssignmentTarget
133137 C.lexeme $ P.char '='
134138 value <- parseValue
135− C.semi
139+ when requireSemi (void C.semi)
136140 return $ Assignment tgt value
137141
138142parseManyStatements :: P.Parsec String () [Statement]
139−parseManyStatements = C.braces $ P.many parseStatement
143+parseManyStatements = C.braces $ P.many (parseStatement True)
140144
141145parseWhile :: P.Parsec String () Statement
142146parseWhile = While <$> (C.reserved "while" *> C.parens parseValue)
@@ -146,9 +150,9 @@ parseFor :: P.Parsec String () Statement
146150parseFor = For <$> (C.reserved "for" *> C.parens forIntro)
147151 <*> parseManyStatements
148152 where
149− forIntro = (,,) <$> parseStatement
153+ forIntro = (,,) <$> parseStatement False
150154 <*> (C.semi *> parseValue)
151− <*> (C.semi *> parseStatement)
155+ <*> (C.semi *> parseStatement False)
152156
153157parseIfThenElse :: P.Parsec String () Statement
154158parseIfThenElse = IfThenElse
@@ -156,17 +160,17 @@ parseIfThenElse = IfThenElse
156160 <*> parseManyStatements
157161 <*> P.optionMaybe (C.reserved "else" *> parseManyStatements)
158162
159−parseReturn :: P.Parsec String () Statement
160−parseReturn = Return <$> (C.reserved "return" *> parseValue <* C.semi)
163+parseReturn :: Bool -> P.Parsec String () Statement
164+parseReturn requireSemi = Return <$> (C.reserved "return" *> parseValue <* when requireSemi (void C.semi))
161165
162−parseStatement :: P.Parsec String () Statement
163−parseStatement = P.choice $ map P.try
164− [ parseVariableIntroduction
165− , parseAssignment
166+parseStatement :: Bool -> P.Parsec String () Statement
167+parseStatement requireSemi = P.choice $ map P.try
168+ [ parseVariableIntroduction requireSemi
169+ , parseAssignment requireSemi
166170 , parseWhile
167171 , parseFor
168172 , parseIfThenElse
169− , parseReturn ]
173+ , parseReturn requireSemi ]
170174
171175parseStringBinder :: P.Parsec String () Binder
172176parseStringBinder = StringBinder <$> C.stringLiteral
@@ -210,3 +214,9 @@ parseBinder = P.choice $ map P.try
210214 , parseObjectBinder
211215 , parseArrayBinder
212216 , C.parens parseBinder ]
217+
218+parseAssignmentTarget :: P.Parsec String () AssignmentTarget
219+parseAssignmentTarget = buildExpressionParser operators (AssignVariable <$> C.identifier)
220+ where
221+ operators = [ [ Postfix $ AssignArrayIndex <$> C.squares parseValue
222+ , Postfix $ AssignObjectProperty <$> (C.dot *> C.identifier) ] ]