on master help sign in
Fix parser when . or - come right after a (

Fix #1532 and fix #1536 by trying to parse normal expressions first. This way you commit to (.x) before trying (.). A special case was needed to try (-) before committing to (-2) so both cases will work. Also add tests for parsing record accessors and parsing negative numbers.

commit47e71baead6711931374eb2874de84d532c332ae authorEvan Czaplicki <evancz@users.noreply.github.com> dateSun 18 Dec 2016, 20:17 (10 years ago) parent6ff3a44
6 files changed+117−13
src/Parse/Expression.hs+29−12 src/Parse/Helpers.hs+8−1 tests/test-files/good-expected-js/Literals/Negatives.elm.js+22 tests/test-files/good-expected-js/Records/Access.elm.js+19 tests/test-files/good/Literals/Negatives.elm+17 tests/test-files/good/Records/Access.elm+22
src/Parse/Expression.hs+29−12
@@ -114,20 +114,32 @@ listHelp start entries =
114114tuple :: R.Position -> Parser Src.RawExpr
115115tuple start =
116116 do leftParen
117+ pos <- getPosition
118+ spos <- whitespace
117119 inContext start E.ExprTuple $ oneOf $
118− [ do op <- infixOp
120+ [ do noSpace pos spos
121+ try (minus >> rightParen)
122+ end <- getPosition
123+ return $ mkBinop start end "-"
124+
125+ , do checkSpace spos
126+ (entry, _, spos2) <- expression
127+ checkSpace spos2
128+ tupleHelp start [entry]
129+
130+ , do noSpace pos spos
131+ op <- infixOp
119132 rightParen
120133 end <- getPosition
121− let x = A.at start end (Src.var "x")
122− let y = A.at start end (Src.var "y")
123− return $ mkLambda start end "x" $ mkLambda start end "y" $
124− A.at start end (Src.Binop [(x, A.at start end op)] y)
134+ return $ mkBinop start end op
125135
126− , do rightParen
136+ , do noSpace pos spos
137+ rightParen
127138 end <- getPosition
128139 return (A.at start end (Src.tuple []))
129140
130− , do comma
141+ , do noSpace pos spos
142+ comma
131143 arity <- chompCommas 2
132144 rightParen
133145 end <- getPosition
@@ -135,11 +147,6 @@ tuple start =
135147 let ann x = A.at start end x
136148 let result = ann (Src.tuple (map (ann . Src.var) args))
137149 return (foldr (mkLambda start end) result args)
138−
139− , do spaces
140− (entry, _, pos) <- expression
141− checkSpace pos
142− tupleHelp start [entry]
143150 ]
144151
145152
@@ -148,6 +155,16 @@ mkLambda start end arg body =
148155 A.at start end (Src.Lambda (A.at start end (P.Var arg)) body)
149156
150157
158+mkBinop :: R.Position -> R.Position -> Text -> Src.RawExpr
159+mkBinop start end op =
160+ let
161+ x = A.at start end (Src.var "x")
162+ y = A.at start end (Src.var "y")
163+ in
164+ mkLambda start end "x" $ mkLambda start end "y" $
165+ A.at start end (Src.Binop [(x, A.at start end op)] y)
166+
167+
151168chompCommas :: Int -> Parser Int
152169chompCommas n =
153170 oneOf
src/Parse/Helpers.hs+8−1
@@ -7,7 +7,7 @@ module Parse.Helpers
77 , equals, rightArrow, hasType, comma, pipe, cons, dot, minus, lambda
88 , leftParen, rightParen, leftSquare, rightSquare, leftCurly, rightCurly
99 , addLocation, inContext
10− , spaces, checkSpace, checkAligned, checkFreshLine
10+ , spaces, noSpace, checkSpace, checkAligned, checkFreshLine
1111 )
1212 where
1313
@@ -194,6 +194,13 @@ spaces =
194194 checkSpace =<< whitespace
195195
196196
197+noSpace :: R.Position -> SPos -> Parser ()
198+noSpace pos (SPos spos) =
199+ if pos == spos
200+ then return ()
201+ else deadend []
202+
203+
197204checkSpace :: SPos -> Parser ()
198205checkSpace (SPos (R.Position _ col)) =
199206 do indent <- getIndent
tests/test-files/good-expected-js/Literals/Negatives.elm.jsnew file+22
@@ -0,0 +1,22 @@
1+var _elm_lang$core$Main_ops = _elm_lang$core$Main_ops || {};
2+_elm_lang$core$Main_ops['-'] = F2(
3+ function (x, y) {
4+ return x;
5+ });
6+var _elm_lang$core$Main$minus = A2(_elm_lang$core$Main_ops['-'], 3, 4);
7+var _elm_lang$core$Main$minusNegative = A2(
8+ _elm_lang$core$Main_ops['-'],
9+ 3,
10+ A2(_elm_lang$core$Main_ops['-'], 0, 4));
11+var _elm_lang$core$Main$negativeMinusNegative = A2(
12+ _elm_lang$core$Main_ops['-'],
13+ A2(_elm_lang$core$Main_ops['-'], 0, 3),
14+ A2(_elm_lang$core$Main_ops['-'], 0, 4));
15+var _elm_lang$core$Main$negativeInParens = A2(_elm_lang$core$Main_ops['-'], 0, 2);
16+var _elm_lang$core$Main$funcMinus = A2(
17+ F2(
18+ function (x, y) {
19+ return A2(_elm_lang$core$Main_ops['-'], x, y);
20+ }),
21+ 3,
22+ 4);
tests/test-files/good-expected-js/Records/Access.elm.jsnew file+19
@@ -0,0 +1,19 @@
1+var _elm_lang$core$Main$apply = F2(
2+ function (f, x) {
3+ return f(x);
4+ });
5+var _elm_lang$core$Main$point = {x: 3, y: 4};
6+var _elm_lang$core$Main$x1 = _elm_lang$core$Main$point.x;
7+var _elm_lang$core$Main$x2 = function (r) {
8+ return r.x;
9+}(_elm_lang$core$Main$point);
10+var _elm_lang$core$Main$x3 = _elm_lang$core$Main$point.x;
11+var _elm_lang$core$Main$x4 = function (r) {
12+ return r.x;
13+}(_elm_lang$core$Main$point);
14+var _elm_lang$core$Main$x5 = A2(
15+ _elm_lang$core$Main$apply,
16+ function (r) {
17+ return r.x;
18+ },
19+ _elm_lang$core$Main$point);
tests/test-files/good/Literals/Negatives.elmnew file+17
@@ -0,0 +1,17 @@
1+
2+(-) x y = x
3+
4+minus =
5+ 3 - 4
6+
7+minusNegative =
8+ 3 - -4
9+
10+negativeMinusNegative =
11+ -3 - -4
12+
13+negativeInParens =
14+ (-2)
15+
16+funcMinus =
17+ (-) 3 4
tests/test-files/good/Records/Access.elmnew file+22
@@ -0,0 +1,22 @@
1+
2+point =
3+ { x = 3, y = 4 }
4+
5+x1 =
6+ point.x
7+
8+x2 =
9+ .x point
10+
11+x3 =
12+ (point).x
13+
14+x4 =
15+ (.x) point
16+
17+
18+apply f x = f x
19+
20+x5 =
21+ apply .x point
22+