@@ -159,9 +159,168 @@ void Parser::OutOfMemory()
159
159
throw ParseExceptionObject (ERRnoMemory);
160
160
}
161
161
162
- void Parser::Error (HRESULT hr)
162
+ LPCWSTR Parser::GetTokenString (tokens token)
163
+ {
164
+ switch (token)
165
+ {
166
+ case tkNone : return _u (" " );
167
+ case tkEOF : return _u (" end of script" );
168
+ case tkIntCon : return _u (" integer literal" );
169
+ case tkFltCon : return _u (" float literal" );
170
+ case tkStrCon : return _u (" string literal" );
171
+ case tkRegExp : return _u (" regular expression literal" );
172
+
173
+ // keywords
174
+ case tkABSTRACT : return _u (" abstract" );
175
+ case tkASSERT : return _u (" assert" );
176
+ case tkAWAIT : return _u (" await" );
177
+ case tkBOOLEAN : return _u (" boolean" );
178
+ case tkBREAK : return _u (" break" );
179
+ case tkBYTE : return _u (" byte" );
180
+ case tkCASE : return _u (" case" );
181
+ case tkCATCH : return _u (" catch" );
182
+ case tkCHAR : return _u (" char" );
183
+ case tkCONTINUE : return _u (" continue" );
184
+ case tkDEBUGGER : return _u (" debugger" );
185
+ case tkDECIMAL : return _u (" decimal" );
186
+ case tkDEFAULT : return _u (" default" );
187
+ case tkDELETE : return _u (" delete" );
188
+ case tkDO : return _u (" do" );
189
+ case tkDOUBLE : return _u (" double" );
190
+ case tkELSE : return _u (" else" );
191
+ case tkENSURE : return _u (" ensure" );
192
+ case tkEVENT : return _u (" event" );
193
+ case tkFALSE : return _u (" false" );
194
+ case tkFINAL : return _u (" final" );
195
+ case tkFINALLY : return _u (" finally" );
196
+ case tkFLOAT : return _u (" float" );
197
+ case tkFOR : return _u (" for" );
198
+ case tkFUNCTION : return _u (" function" );
199
+ case tkGET : return _u (" get" );
200
+ case tkGOTO : return _u (" goto" );
201
+ case tkIF : return _u (" if" );
202
+ case tkIN : return _u (" in" );
203
+ case tkINSTANCEOF : return _u (" instanceof" );
204
+ case tkINT : return _u (" int" );
205
+ case tkINTERNAL : return _u (" internal" );
206
+ case tkINVARIANT : return _u (" invariant" );
207
+ case tkLONG : return _u (" long" );
208
+ case tkNAMESPACE : return _u (" namespace" );
209
+ case tkNATIVE : return _u (" native" );
210
+ case tkNEW : return _u (" new" );
211
+ case tkNULL : return _u (" null" );
212
+ case tkREQUIRE : return _u (" require" );
213
+ case tkRETURN : return _u (" return" );
214
+ case tkSBYTE : return _u (" sbyte" );
215
+ case tkSET : return _u (" set" );
216
+ case tkSHORT : return _u (" short" );
217
+ case tkSWITCH : return _u (" switch" );
218
+ case tkSYNCHRONIZED : return _u (" synchronized" );
219
+ case tkTHIS : return _u (" this" );
220
+ case tkTHROW : return _u (" throw" );
221
+ case tkTHROWS : return _u (" throws" );
222
+ case tkTRANSIENT : return _u (" transient" );
223
+ case tkTRUE : return _u (" true" );
224
+ case tkTRY : return _u (" try" );
225
+ case tkTYPEOF : return _u (" typeof" );
226
+ case tkUINT : return _u (" uint" );
227
+ case tkULONG : return _u (" ulong" );
228
+ case tkUSE : return _u (" use" );
229
+ case tkUSHORT : return _u (" ushort" );
230
+ case tkVAR : return _u (" var" );
231
+ case tkVOID : return _u (" void" );
232
+ case tkVOLATILE : return _u (" volatile" );
233
+ case tkWHILE : return _u (" while" );
234
+ case tkWITH : return _u (" with" );
235
+
236
+ // Future reserved words that become keywords in ES6
237
+ case tkCLASS : return _u (" class" );
238
+ case tkCONST : return _u (" const" );
239
+ case tkEXPORT : return _u (" export" );
240
+ case tkEXTENDS : return _u (" extends" );
241
+ case tkIMPORT : return _u (" import" );
242
+ case tkLET : return _u (" let" );
243
+ case tkSUPER : return _u (" super" );
244
+ case tkYIELD : return _u (" yield" );
245
+
246
+ // Future reserved words in strict and non-strict modes
247
+ case tkENUM : return _u (" enum" );
248
+
249
+ // Additional future reserved words in strict mode
250
+ case tkIMPLEMENTS : return _u (" implements" );
251
+ case tkINTERFACE : return _u (" interface" );
252
+ case tkPACKAGE : return _u (" package" );
253
+ case tkPRIVATE : return _u (" private" );
254
+ case tkPROTECTED : return _u (" protected" );
255
+ case tkPUBLIC : return _u (" public" );
256
+ case tkSTATIC : return _u (" static" );
257
+
258
+ case tkID: return _u (" identifier" );
259
+
260
+ // Non-operator non-identifier tokens
261
+ case tkSColon: return _u (" ;" );
262
+ case tkRParen: return _u (" )" );
263
+ case tkRBrack: return _u (" ]" );
264
+ case tkLCurly: return _u (" {" );
265
+ case tkRCurly: return _u (" }" );
266
+
267
+ // Operator non-identifier tokens
268
+ case tkComma: return _u (" ," );
269
+ case tkDArrow: return _u (" =>" );
270
+ case tkAsg: return _u (" =" );
271
+ case tkAsgAdd: return _u (" +=" );
272
+ case tkAsgSub: return _u (" -=" );
273
+ case tkAsgMul: return _u (" *=" );
274
+ case tkAsgDiv: return _u (" /=" );
275
+ case tkAsgExpo: return _u (" **=" );
276
+ case tkAsgMod: return _u (" %=" );
277
+ case tkAsgAnd: return _u (" &=" );
278
+ case tkAsgXor: return _u (" ^=" );
279
+ case tkAsgOr: return _u (" |=" );
280
+ case tkAsgLsh: return _u (" <<=" );
281
+ case tkAsgRsh: return _u (" >>=" );
282
+ case tkAsgRs2: return _u (" >>>=" );
283
+ case tkQMark: return _u (" ?" );
284
+ case tkColon: return _u (" :" );
285
+ case tkLogOr: return _u (" ||" );
286
+ case tkLogAnd: return _u (" &&" );
287
+ case tkOr: return _u (" |" );
288
+ case tkXor: return _u (" ^" );
289
+ case tkAnd: return _u (" &" );
290
+ case tkEQ: return _u (" ==" );
291
+ case tkNE: return _u (" !=" );
292
+ case tkEqv: return _u (" ===" );
293
+ case tkNEqv: return _u (" !==" );
294
+ case tkLT: return _u (" <" );
295
+ case tkLE: return _u (" <=" );
296
+ case tkGT: return _u (" >" );
297
+ case tkGE: return _u (" >=" );
298
+ case tkLsh: return _u (" <<" );
299
+ case tkRsh: return _u (" >>" );
300
+ case tkRs2: return _u (" >>>" );
301
+ case tkAdd: return _u (" +" );
302
+ case tkSub: return _u (" -" );
303
+ case tkExpo: return _u (" **" );
304
+ case tkStar: return _u (" *" );
305
+ case tkDiv: return _u (" /" );
306
+ case tkPct: return _u (" %" );
307
+ case tkTilde: return _u (" ~" );
308
+ case tkBang: return _u (" !" );
309
+ case tkInc: return _u (" ++" );
310
+ case tkDec: return _u (" --" );
311
+ case tkEllipsis: return _u (" ..." );
312
+ case tkLParen: return _u (" (" );
313
+ case tkLBrack: return _u (" [" );
314
+ case tkDot: return _u (" ." );
315
+
316
+ default :
317
+ return _u (" unknown token" );
318
+ }
319
+ }
320
+
321
+ void Parser::Error (HRESULT hr, LPCWSTR stringOne, LPCWSTR stringTwo)
163
322
{
164
- throw ParseExceptionObject (hr);
323
+ throw ParseExceptionObject (hr, stringOne, stringTwo );
165
324
}
166
325
167
326
void Parser::Error (HRESULT hr, ParseNodePtr pnode)
@@ -226,6 +385,7 @@ HRESULT Parser::ValidateSyntax(LPCUTF8 pszSrc, size_t encodedCharCount, bool isG
226
385
227
386
HRESULT hr;
228
387
SmartFPUControl smartFpuControl;
388
+ bool handled = false ;
229
389
230
390
BOOL fDeferSave = m_deferringAST;
231
391
try
@@ -287,9 +447,11 @@ HRESULT Parser::ValidateSyntax(LPCUTF8 pszSrc, size_t encodedCharCount, bool isG
287
447
{
288
448
m_deferringAST = fDeferSave ;
289
449
hr = e.GetError ();
450
+ hr = pse->ProcessError (this ->GetScanner (), hr, /* pnodeBase */ NULL , e.GetStringOne (), e.GetStringTwo ());
451
+ handled = true ;
290
452
}
291
453
292
- if (nullptr != pse && FAILED (hr))
454
+ if (handled == false && nullptr != pse && FAILED (hr))
293
455
{
294
456
hr = pse->ProcessError (this ->GetScanner (), hr, /* pnodeBase */ NULL );
295
457
}
@@ -326,6 +488,7 @@ HRESULT Parser::ParseSourceInternal(
326
488
ParseNodeProg * pnodeBase = NULL ;
327
489
HRESULT hr;
328
490
SmartFPUControl smartFpuControl;
491
+ bool handled = false ;
329
492
330
493
try
331
494
{
@@ -364,13 +527,15 @@ HRESULT Parser::ParseSourceInternal(
364
527
catch (ParseExceptionObject& e)
365
528
{
366
529
hr = e.GetError ();
530
+ hr = pse->ProcessError (this ->GetScanner (), hr, pnodeBase, e.GetStringOne (), e.GetStringTwo ());
531
+ handled = true ;
367
532
}
368
533
catch (Js::AsmJsParseException&)
369
534
{
370
535
hr = JSERR_AsmJsCompileError;
371
536
}
372
537
373
- if (FAILED (hr))
538
+ if (handled == false && FAILED (hr))
374
539
{
375
540
hr = pse->ProcessError (this ->GetScanner (), hr, pnodeBase);
376
541
}
@@ -2153,7 +2318,7 @@ IdentPtr Parser::ParseMetaProperty(tokens metaParentKeyword, charcount_t ichMin,
2153
2318
}
2154
2319
else
2155
2320
{
2156
- Error (ERRsyntax );
2321
+ Error (ERRValidIfFollowedBy, _u ( " 'new.' " ), _u ( " 'target' " ) );
2157
2322
}
2158
2323
}
2159
2324
@@ -2442,7 +2607,7 @@ void Parser::ParseImportClause(ModuleImportOrExportEntryList* importEntryList, b
2442
2607
// There cannot be a namespace import or named imports list on the left of the comma in a module import clause.
2443
2608
if (parsingAfterComma || parsedNamespaceOrNamedImport)
2444
2609
{
2445
- Error (ERRsyntax );
2610
+ Error (ERRTokenAfter, _u ( " , " ), GetTokenString ( this -> GetScanner ()-> GetPrevious ()) );
2446
2611
}
2447
2612
2448
2613
this ->GetScanner ()->Scan ();
@@ -2498,7 +2663,7 @@ ParseNodePtr Parser::ParseImport()
2498
2663
{
2499
2664
if (!m_scriptContext->GetConfig ()->IsESDynamicImportEnabled ())
2500
2665
{
2501
- Error (ERRsyntax );
2666
+ Error (ERRExperimental );
2502
2667
}
2503
2668
2504
2669
ParseNodePtr pnode = ParseImportCall<buildAST>();
@@ -3109,7 +3274,7 @@ ParseNodePtr Parser::ParseTerm(BOOL fAllowCall,
3109
3274
// If the token after the right paren is not => or if there was a newline between () and => this is a syntax error
3110
3275
if (!IsDoingFastScan () && (m_token.tk != tkDArrow || this ->GetScanner ()->FHadNewLine ()))
3111
3276
{
3112
- Error (ERRsyntax );
3277
+ Error (ERRValidIfFollowedBy, _u ( " Lambda parameter list " ), _u ( " '=>' on the same line " ) );
3113
3278
}
3114
3279
3115
3280
if (buildAST)
@@ -3423,7 +3588,18 @@ ParseNodePtr Parser::ParseTerm(BOOL fAllowCall,
3423
3588
3424
3589
default :
3425
3590
LUnknown:
3426
- Error (ERRsyntax);
3591
+ if (m_token.tk == tkNone)
3592
+ {
3593
+ Error (ERRInvalidIdentifier, m_token.GetIdentifier (this ->GetHashTbl ())->Psz (), GetTokenString (GetScanner ()->GetPrevious ()));
3594
+ }
3595
+ else if (m_token.IsKeyword ())
3596
+ {
3597
+ Error (ERRKeywordAfter, GetTokenString (m_token.tk ), GetTokenString (GetScanner ()->GetPrevious ()));
3598
+ }
3599
+ else
3600
+ {
3601
+ Error (ERRTokenAfter, GetTokenString (m_token.tk ), GetTokenString (GetScanner ()->GetPrevious ()));
3602
+ }
3427
3603
break ;
3428
3604
}
3429
3605
@@ -5607,7 +5783,7 @@ void Parser::ParseFncDeclHelper(ParseNodeFnc * pnodeFnc, LPCOLESTR pNameHint, us
5607
5783
// this after verifying there was a => token. Otherwise we would throw the wrong error.
5608
5784
if (hadNewLine)
5609
5785
{
5610
- Error (ERRsyntax );
5786
+ Error (ERRValidIfFollowedBy, _u ( " Lambda parameter list " ), _u ( " '=>' on the same line " ) );
5611
5787
}
5612
5788
}
5613
5789
@@ -11893,6 +12069,7 @@ HRESULT Parser::ParseFunctionInBackground(ParseNodeFnc * pnodeFnc, ParseContext
11893
12069
ParseNodeBlock * pnodeBlock = StartParseBlock<true >(PnodeBlockType::Function, ScopeType_FunctionBody);
11894
12070
pnodeFnc->pnodeScopes = pnodeBlock;
11895
12071
m_ppnodeScope = &pnodeBlock->pnodeScopes ;
12072
+ bool handled = false ;
11896
12073
11897
12074
uint uDeferSave = m_grfscr & (fscrCanDeferFncParse | fscrWillDeferFncParse);
11898
12075
@@ -11943,9 +12120,11 @@ HRESULT Parser::ParseFunctionInBackground(ParseNodeFnc * pnodeFnc, ParseContext
11943
12120
catch (ParseExceptionObject& e)
11944
12121
{
11945
12122
hr = e.GetError ();
12123
+ hr = pse->ProcessError (this ->GetScanner (), hr, nullptr , e.GetStringOne (), e.GetStringTwo ());
12124
+ handled = true ;
11946
12125
}
11947
12126
11948
- if (FAILED (hr))
12127
+ if (handled == false && FAILED (hr))
11949
12128
{
11950
12129
hr = pse->ProcessError (this ->GetScanner (), hr, nullptr );
11951
12130
}
0 commit comments