Skip to content

Commit b2f5f1b

Browse files
Basic parsing
1 parent 2f15d4e commit b2f5f1b

File tree

7 files changed

+33
-14
lines changed

7 files changed

+33
-14
lines changed

lib/Parser/Parse.cpp

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ LPCWSTR Parser::GetTokenString(tokens token)
309309
case tkLParen: return _u("(");
310310
case tkLBrack: return _u("[");
311311
case tkDot: return _u(".");
312+
case tkOptChain: return _u("?.");
312313

313314
default:
314315
return _u("unknown token");
@@ -894,13 +895,13 @@ ParseNodeUni * Parser::CreateUniNode(OpCode nop, ParseNodePtr pnode1, charcount_
894895
}
895896

896897
// Create ParseNodeBin
897-
ParseNodeBin * Parser::StaticCreateBinNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2, ArenaAllocator* alloc, charcount_t ichMin, charcount_t ichLim)
898+
ParseNodeBin * Parser::StaticCreateBinNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2, ArenaAllocator* alloc, charcount_t ichMin, charcount_t ichLim, bool isNullPropagating)
898899
{
899900
DebugOnly(VerifyNodeSize(nop, sizeof(ParseNodeBin)));
900-
return Anew(alloc, ParseNodeBin, nop, ichMin, ichLim, pnode1, pnode2);
901+
return Anew(alloc, ParseNodeBin, nop, ichMin, ichLim, pnode1, pnode2, isNullPropagating);
901902
}
902903

903-
ParseNodeBin * Parser::CreateBinNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2)
904+
ParseNodeBin * Parser::CreateBinNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2, bool isNullPropagating)
904905
{
905906
Assert(!this->m_deferringAST);
906907
charcount_t ichMin;
@@ -937,15 +938,15 @@ ParseNodeBin * Parser::CreateBinNode(OpCode nop, ParseNodePtr pnode1, ParseNodeP
937938
}
938939
}
939940

940-
return CreateBinNode(nop, pnode1, pnode2, ichMin, ichLim);
941+
return CreateBinNode(nop, pnode1, pnode2, ichMin, ichLim, isNullPropagating);
941942
}
942943

943944

944945
ParseNodeBin * Parser::CreateBinNode(OpCode nop, ParseNodePtr pnode1,
945-
ParseNodePtr pnode2, charcount_t ichMin, charcount_t ichLim)
946+
ParseNodePtr pnode2, charcount_t ichMin, charcount_t ichLim, bool isNullPropagating)
946947
{
947948
Assert(!this->m_deferringAST);
948-
ParseNodeBin * pnode = StaticCreateBinNode(nop, pnode1, pnode2, &m_nodeAllocator, ichMin, ichLim);
949+
ParseNodeBin * pnode = StaticCreateBinNode(nop, pnode1, pnode2, &m_nodeAllocator, ichMin, ichLim, isNullPropagating);
949950
AddAstSize(sizeof(ParseNodeBin));
950951
return pnode;
951952
}
@@ -4163,12 +4164,17 @@ ParseNodePtr Parser::ParsePostfixOperators(
41634164
}
41644165
}
41654166
break;
4166-
4167+
4168+
case tkOptChain:
41674169
case tkDot:
41684170
{
41694171
ParseNodePtr name = nullptr;
41704172
OpCode opCode = knopDot;
41714173

4174+
bool isNullPropagating = tkOptChain == m_token.tk;
4175+
// We don't use a custom token but rather tell that knopDot is null-propagating
4176+
// opCode = knopOptChain;
4177+
41724178
this->GetScanner()->Scan();
41734179
if (!m_token.IsIdentifier())
41744180
{
@@ -4189,7 +4195,7 @@ ParseNodePtr Parser::ParsePostfixOperators(
41894195

41904196
if (buildAST)
41914197
{
4192-
if (opCode == knopDot)
4198+
if (opCode == knopDot || opCode == knopOptChain)
41934199
{
41944200
name = CreateNameNode(m_token.GetIdentifier(this->GetHashTbl()));
41954201
}
@@ -4205,7 +4211,7 @@ ParseNodePtr Parser::ParsePostfixOperators(
42054211
}
42064212
else
42074213
{
4208-
pnode = CreateBinNode(opCode, pnode, name);
4214+
pnode = CreateBinNode(opCode, pnode, name, isNullPropagating);
42094215
}
42104216
}
42114217
else

lib/Parser/Parse.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -371,16 +371,16 @@ class Parser
371371
return Anew(alloc, typename OpCodeTrait<nop>::ParseNodeType, nop, ichMin, ichLim);
372372
}
373373

374-
static ParseNodeBin * StaticCreateBinNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2, ArenaAllocator* alloc, charcount_t ichMin = 0, charcount_t ichLim = 0);
374+
static ParseNodeBin * StaticCreateBinNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2, ArenaAllocator* alloc, charcount_t ichMin = 0, charcount_t ichLim = 0, bool isNullPropagating = false);
375375
static ParseNodeBlock * StaticCreateBlockNode(ArenaAllocator* alloc, charcount_t ichMin = 0, charcount_t ichLim = 0, int blockId = -1, PnodeBlockType blockType = PnodeBlockType::Regular);
376376
static ParseNodeVar * StaticCreateTempNode(ParseNode* initExpr, ArenaAllocator* alloc);
377377
static ParseNodeUni * StaticCreateTempRef(ParseNode* tempNode, ArenaAllocator* alloc);
378378

379379
private:
380380
ParseNodeUni * CreateUniNode(OpCode nop, ParseNodePtr pnodeOp);
381381
ParseNodeUni * CreateUniNode(OpCode nop, ParseNodePtr pnode1, charcount_t ichMin, charcount_t ichLim);
382-
ParseNodeBin * CreateBinNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2);
383-
ParseNodeBin * CreateBinNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2, charcount_t ichMin, charcount_t ichLim);
382+
ParseNodeBin * CreateBinNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2, bool isNullPropagating = false);
383+
ParseNodeBin * CreateBinNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2, charcount_t ichMin, charcount_t ichLim, bool isNullPropagating = false);
384384
ParseNodeTri * CreateTriNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2, ParseNodePtr pnode3);
385385
ParseNodeTri * CreateTriNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2, ParseNodePtr pnode3, charcount_t ichMin, charcount_t ichLim);
386386
ParseNodeBlock * CreateBlockNode(PnodeBlockType blockType = PnodeBlockType::Regular);

lib/Parser/Scan.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//-------------------------------------------------------------------------------------------------------
22
// Copyright (C) Microsoft. All rights reserved.
3+
// Copyright (c) ChakraCore Project Contributors. All rights reserved.
34
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
45
//-------------------------------------------------------------------------------------------------------
56
#include "ParserPch.h"
@@ -1780,6 +1781,12 @@ tokens Scanner<EncodingPolicy>::ScanCore(bool identifyKwds)
17801781
token = tkCoalesce;
17811782
break;
17821783
}
1784+
else if (this->PeekFirst(p, last) == '.') // ToDo: Config flag for optional chaining?!
1785+
{
1786+
p++;
1787+
token = tkOptChain;
1788+
break;
1789+
}
17831790
break;
17841791

17851792
case '{': Assert(chType == _C_LC); token = tkLCurly; break;

lib/Parser/kwd-lsc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//-------------------------------------------------------------------------------------------------------
22
// Copyright (C) Microsoft. All rights reserved.
3+
// Copyright (c) ChakraCore Project Contributors. All rights reserved.
34
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
45
//-------------------------------------------------------------------------------------------------------
56
#ifndef KEYWORD
@@ -174,6 +175,7 @@ TOK_DCL(tkEllipsis , No, knopNone ,Spr, knopEllipsis ) // ...
174175
TOK_DCL(tkLParen , No, knopNone , No, knopNone ) // (
175176
TOK_DCL(tkLBrack , No, knopNone , No, knopNone ) // [
176177
TOK_DCL(tkDot , No, knopNone , No, knopNone ) // .
178+
TOK_DCL(tkOptChain , No, knopNone , No, knopNone ) // ?.
177179

178180
// String template tokens
179181
TOK_DCL(tkStrTmplBasic , No, knopNone , No, knopNone ) // `...`

lib/Parser/ptlist.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//-------------------------------------------------------------------------------------------------------
22
// Copyright (C) Microsoft. All rights reserved.
3+
// Copyright (c) ChakraCore Project Contributors. All rights reserved.
34
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
45
//-------------------------------------------------------------------------------------------------------
56
/*****************************************************************************/
@@ -80,6 +81,7 @@ PTNODE(knopGe , ">=" , OP(Ge) , Bin , fnopBin|fn
8081
PTNODE(knopGt , ">" , OP(Gt) , Bin , fnopBin|fnopRel , "GreaterThanOper" )
8182
PTNODE(knopCall , "()" , Nop , Call , fnopNone , "CallExpr" )
8283
PTNODE(knopDot , "." , Nop , Bin , fnopBin , "DotOper" )
84+
PTNODE(knopOptChain , "?." , Nop , Bin , fnopBin , "OptChain" )
8385
PTNODE(knopAsg , "=" , Nop , Bin , fnopBin|fnopAsg , "AssignmentOper" )
8486
PTNODE(knopInstOf , "instanceof" , IsInst , Bin , fnopBin|fnopRel , "InstanceOfExpr" )
8587
PTNODE(knopIn , "in" , IsIn , Bin , fnopBin|fnopRel , "InOper" )

lib/Parser/ptree.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ ParseNodeUni::ParseNodeUni(OpCode nop, charcount_t ichMin, charcount_t ichLim, P
301301
this->pnode1 = pnode1;
302302
}
303303

304-
ParseNodeBin::ParseNodeBin(OpCode nop, charcount_t ichMin, charcount_t ichLim, ParseNode * pnode1, ParseNode * pnode2)
304+
ParseNodeBin::ParseNodeBin(OpCode nop, charcount_t ichMin, charcount_t ichLim, ParseNode * pnode1, ParseNode * pnode2, bool isNullPropagating)
305305
: ParseNode(nop, ichMin, ichLim)
306306
{
307307
// Member name is either a string or a computed name
@@ -313,6 +313,7 @@ ParseNodeBin::ParseNodeBin(OpCode nop, charcount_t ichMin, charcount_t ichLim, P
313313

314314
this->pnode1 = pnode1;
315315
this->pnode2 = pnode2;
316+
this->isNullPropagating = isNullPropagating;
316317

317318
// Statically detect if the add is a concat
318319
if (!PHASE_OFF1(Js::ByteCodeConcatExprOptPhase))

lib/Parser/ptree.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,10 +277,11 @@ class ParseNodeUni : public ParseNode
277277
class ParseNodeBin : public ParseNode
278278
{
279279
public:
280-
ParseNodeBin(OpCode nop, charcount_t ichMin, charcount_t ichLim, ParseNode * pnode1, ParseNode * pnode2);
280+
ParseNodeBin(OpCode nop, charcount_t ichMin, charcount_t ichLim, ParseNode * pnode1, ParseNode * pnode2, bool isNullPropagating = false);
281281

282282
ParseNodePtr pnode1;
283283
ParseNodePtr pnode2;
284+
bool isNullPropagating;
284285

285286
DISABLE_SELF_CAST(ParseNodeBin);
286287
};

0 commit comments

Comments
 (0)