Mercurial > projects > dil
comparison trunk/src/dil/Parser.d @ 484:265c0b655f18
Added more calls to set().
Removed method skipToOnePast().
Added methods start2() and isNodeSet().
author | Aziz K?ksal <aziz.koeksal@gmail.com> |
---|---|
date | Mon, 26 Nov 2007 20:18:54 +0100 |
parents | 180711cc4b66 |
children | ea8c7459f1c4 |
comparison
equal
deleted
inserted
replaced
483:180711cc4b66 | 484:265c0b655f18 |
---|---|
73 { | 73 { |
74 lx.nextToken(); | 74 lx.nextToken(); |
75 token = lx.token; | 75 token = lx.token; |
76 } while (token.isWhitespace) // Skip whitespace | 76 } while (token.isWhitespace) // Skip whitespace |
77 } | 77 } |
78 /+ | 78 |
79 void skipToOnePast(TOK tok) | 79 /++ |
80 { | 80 Start the parser and return the parsed Declarations. |
81 for (; token.type != tok && token.type != T.EOF; nT()) | 81 +/ |
82 {} | 82 Declarations start() |
83 nT(); | 83 { |
84 } | 84 init(); |
85 +/ | 85 auto begin = token; |
86 auto decls = new Declarations; | |
87 if (token.type == T.Module) | |
88 decls ~= parseModuleDeclaration(); | |
89 decls ~= parseDeclarationDefinitions(); | |
90 set(decls, begin); | |
91 return decls; | |
92 } | |
93 | |
94 /++ | |
95 Start the parser and return the parsed Expression. | |
96 +/ | |
97 Expression start2() | |
98 { | |
99 init(); | |
100 return parseExpression(); | |
101 } | |
102 | |
86 uint trying; | 103 uint trying; |
87 uint errorCount; | 104 uint errorCount; |
88 | 105 |
89 /++ | 106 /++ |
90 This method executes the delegate parseMethod and when an error occurred | 107 This method executes the delegate parseMethod and when an error occurred |
115 success = true; | 132 success = true; |
116 --trying; | 133 --trying; |
117 return result; | 134 return result; |
118 } | 135 } |
119 | 136 |
137 /++ | |
138 Sets the begin and end tokens of an AST node. | |
139 +/ | |
120 Class set(Class)(Class node, Token* begin) | 140 Class set(Class)(Class node, Token* begin) |
121 { | 141 { |
122 node.setTokens(begin, this.prevToken); | 142 node.setTokens(begin, this.prevToken); |
123 return node; | 143 return node; |
144 } | |
145 | |
146 /++ | |
147 Returns true if set() has been called on a node, or false otherwise. | |
148 +/ | |
149 bool isNodeSet(Node node) | |
150 { | |
151 return node.begin !is null && node.end !is null; | |
124 } | 152 } |
125 | 153 |
126 TOK peekNext() | 154 TOK peekNext() |
127 { | 155 { |
128 auto state = lx.getState(); | 156 auto state = lx.getState(); |
147 | 175 |
148 /++++++++++++++++++++++++++++++ | 176 /++++++++++++++++++++++++++++++ |
149 + Declaration parsing methods + | 177 + Declaration parsing methods + |
150 ++++++++++++++++++++++++++++++/ | 178 ++++++++++++++++++++++++++++++/ |
151 | 179 |
152 Declarations start() | |
153 { | |
154 init(); | |
155 auto decls = new Declarations; | |
156 if (token.type == T.Module) | |
157 decls ~= parseModuleDeclaration(); | |
158 decls ~= parseDeclarationDefinitions(); | |
159 return decls; | |
160 } | |
161 | |
162 Declaration parseModuleDeclaration() | 180 Declaration parseModuleDeclaration() |
163 { | 181 { |
164 auto begin = token; | 182 auto begin = token; |
165 ModuleFQN moduleFQN; | 183 ModuleFQN moduleFQN; |
166 do | 184 do |
185 { } | 203 { } |
186 { DeclDefs } | 204 { DeclDefs } |
187 */ | 205 */ |
188 Declarations parseDeclarationDefinitionsBlock() | 206 Declarations parseDeclarationDefinitionsBlock() |
189 { | 207 { |
208 auto begin = token; | |
190 auto decls = new Declarations; | 209 auto decls = new Declarations; |
191 require(T.LBrace); | 210 require(T.LBrace); |
192 while (token.type != T.RBrace && token.type != T.EOF) | 211 while (token.type != T.RBrace && token.type != T.EOF) |
193 decls ~= parseDeclarationDefinition(); | 212 decls ~= parseDeclarationDefinition(); |
194 require(T.RBrace); | 213 require(T.RBrace); |
195 return decls; | 214 return set(decls, token); |
196 } | 215 } |
197 | 216 |
198 Declaration parseDeclarationDefinition() | 217 Declaration parseDeclarationDefinition() |
199 { | 218 { |
200 auto begin = token; | 219 auto begin = token; |
361 break; | 380 break; |
362 case T.Colon: | 381 case T.Colon: |
363 if (noColon == true) | 382 if (noColon == true) |
364 goto default; | 383 goto default; |
365 nT(); | 384 nT(); |
385 auto begin = token; | |
366 auto decls = new Declarations; | 386 auto decls = new Declarations; |
367 while (token.type != T.RBrace && token.type != T.EOF) | 387 while (token.type != T.RBrace && token.type != T.EOF) |
368 decls ~= parseDeclarationDefinition(); | 388 decls ~= parseDeclarationDefinition(); |
369 d = decls; | 389 d = set(decls, begin); |
370 break; | 390 break; |
371 default: | 391 default: |
372 d = parseDeclarationDefinition(); | 392 d = parseDeclarationDefinition(); |
373 } | 393 } |
394 assert(isNodeSet(d)); | |
374 return d; | 395 return d; |
375 } | 396 } |
376 | 397 |
377 Declaration parseDeclarationsBlockNoColon() | 398 Declaration parseDeclarationsBlockNoColon() |
378 { | 399 { |
815 require(T.RParen); | 836 require(T.RParen); |
816 | 837 |
817 if (token.type == T.Semicolon) | 838 if (token.type == T.Semicolon) |
818 { | 839 { |
819 nT(); | 840 nT(); |
841 // TODO: call set()? | |
820 decls = new EmptyDeclaration(); | 842 decls = new EmptyDeclaration(); |
821 } | 843 } |
822 else | 844 else |
823 decls = parseDeclarationsBlock(); | 845 decls = parseDeclarationsBlock(); |
824 | 846 |
1016 nT(); | 1038 nT(); |
1017 } | 1039 } |
1018 else if (token.type == T.LBrace) | 1040 else if (token.type == T.LBrace) |
1019 { | 1041 { |
1020 hasBody = true; | 1042 hasBody = true; |
1021 // TODO: think about setting a member status variable to a flag InClassBody... this way we can check for DeclDefs that are illegal in class bodies in the parsing phase. | |
1022 decls = parseDeclarationDefinitionsBlock(); | 1043 decls = parseDeclarationDefinitionsBlock(); |
1023 } | 1044 } |
1024 else | 1045 else |
1025 expected(T.LBrace); // TODO: better error msg | 1046 expected(T.LBrace); // TODO: better error msg |
1026 | 1047 |
1481 TemplateInstance: | 1502 TemplateInstance: |
1482 Identifier !( TemplateArguments ) | 1503 Identifier !( TemplateArguments ) |
1483 +/ | 1504 +/ |
1484 DotListType parseDotListType() | 1505 DotListType parseDotListType() |
1485 { | 1506 { |
1507 auto begin = token; | |
1486 Type[] identList; | 1508 Type[] identList; |
1487 if (token.type == T.Dot) | 1509 if (token.type == T.Dot) |
1488 { | 1510 { |
1489 identList ~= new IdentifierType(token); | 1511 identList ~= set(new IdentifierType(token), begin); |
1490 nT(); | 1512 nT(); |
1491 } | 1513 } |
1492 else if (token.type == T.Typeof) | 1514 else if (token.type == T.Typeof) |
1493 { | 1515 { |
1494 requireNext(T.LParen); | 1516 requireNext(T.LParen); |
1495 identList ~= new TypeofType(parseExpression()); | 1517 identList ~= set(new TypeofType(parseExpression()), begin); |
1496 require(T.RParen); | 1518 require(T.RParen); |
1497 if (token.type != T.Dot) | 1519 if (token.type != T.Dot) |
1498 goto Lreturn; | 1520 goto Lreturn; |
1499 nT(); | 1521 nT(); |
1500 } | 1522 } |
1501 | 1523 |
1502 while (1) | 1524 while (1) |
1503 { | 1525 { |
1504 auto begin2 = token; | 1526 begin = token; |
1505 auto ident = requireId(); | 1527 auto ident = requireId(); |
1506 // NB.: Currently Types can't be followed by "!=" so we don't need to peek for "(" when parsing TemplateInstances. | 1528 // NB.: Currently Types can't be followed by "!=" so we don't need to peek for "(" when parsing TemplateInstances. |
1507 if (token.type == T.Not/+ && peekNext() == T.LParen+/) // Identifier !( TemplateArguments ) | 1529 if (token.type == T.Not/+ && peekNext() == T.LParen+/) // Identifier !( TemplateArguments ) |
1508 { | 1530 { |
1509 nT(); // Skip !. | 1531 nT(); // Skip !. |
1510 identList ~= set(new TemplateInstanceType(ident, parseTemplateArguments()), begin2); | 1532 identList ~= set(new TemplateInstanceType(ident, parseTemplateArguments()), begin); |
1511 } | 1533 } |
1512 else // Identifier | 1534 else // Identifier |
1513 identList ~= set(new IdentifierType(ident), begin2); | 1535 identList ~= set(new IdentifierType(ident), begin); |
1514 | 1536 |
1515 if (token.type != T.Dot) | 1537 if (token.type != T.Dot) |
1516 break; | 1538 break; |
1517 nT(); | 1539 nT(); |
1518 } | 1540 } |
1551 Token* mixinIdent; | 1573 Token* mixinIdent; |
1552 | 1574 |
1553 // This code is similar to parseDotListType(). | 1575 // This code is similar to parseDotListType(). |
1554 if (token.type == T.Dot) | 1576 if (token.type == T.Dot) |
1555 { | 1577 { |
1556 templateIdent ~= new IdentifierExpression(token); | 1578 templateIdent ~= set(new IdentifierExpression(token), begin); |
1557 nT(); | 1579 nT(); |
1558 } | 1580 } |
1559 | 1581 |
1560 while (1) | 1582 while (1) |
1561 { | 1583 { |
1584 begin = token; | |
1562 auto ident = requireId(); | 1585 auto ident = requireId(); |
1563 Expression e; | 1586 Expression e; |
1564 if (token.type == T.Not) // Identifier !( TemplateArguments ) | 1587 if (token.type == T.Not) // Identifier !( TemplateArguments ) |
1565 { | 1588 { |
1566 // No need to peek for T.LParen. This must be a template instance. | 1589 // No need to peek for T.LParen. This must be a template instance. |
1567 nT(); | 1590 nT(); |
1568 e = new TemplateInstanceExpression(ident, parseTemplateArguments()); | 1591 e = set(new TemplateInstanceExpression(ident, parseTemplateArguments()), begin); |
1569 } | 1592 } |
1570 else // Identifier | 1593 else // Identifier |
1571 e = new IdentifierExpression(ident); | 1594 e = set(new IdentifierExpression(ident), begin); |
1572 | 1595 |
1573 templateIdent ~= e; | 1596 templateIdent ~= e; |
1574 | 1597 |
1575 if (token.type != T.Dot) | 1598 if (token.type != T.Dot) |
1576 break; | 1599 break; |
2005 Statement ifBody, elseBody; | 2028 Statement ifBody, elseBody; |
2006 | 2029 |
2007 require(T.LParen); | 2030 require(T.LParen); |
2008 | 2031 |
2009 Token* ident; | 2032 Token* ident; |
2033 auto begin = token; // For start of AutoDeclaration or normal Declaration. | |
2010 // auto Identifier = Expression | 2034 // auto Identifier = Expression |
2011 if (token.type == T.Auto) | 2035 if (token.type == T.Auto) |
2012 { | 2036 { |
2013 nT(); | 2037 nT(); |
2014 ident = requireId(); | 2038 ident = requireId(); |
2015 require(T.Assign); | 2039 require(T.Assign); |
2016 auto init = parseExpression(); | 2040 auto init = parseExpression(); |
2017 variable = new AttributeStatement(T.Auto, new DeclarationStatement(new VariableDeclaration(null, [ident], [init]))); | 2041 auto v = new VariableDeclaration(null, [ident], [init]); |
2042 set(v, ident); | |
2043 auto d = new DeclarationStatement(v); | |
2044 set(d, ident); | |
2045 variable = new AttributeStatement(T.Auto, d); | |
2046 set(variable, begin); | |
2018 } | 2047 } |
2019 else | 2048 else |
2020 { | 2049 { |
2021 // Declarator = Expression | 2050 // Declarator = Expression |
2022 Type parseDeclaratorAssign() | 2051 Type parseDeclaratorAssign() |
2028 bool success; | 2057 bool success; |
2029 auto type = try_(&parseDeclaratorAssign, success); | 2058 auto type = try_(&parseDeclaratorAssign, success); |
2030 if (success) | 2059 if (success) |
2031 { | 2060 { |
2032 auto init = parseExpression(); | 2061 auto init = parseExpression(); |
2033 variable = new DeclarationStatement(new VariableDeclaration(type, [ident], [init])); | 2062 auto v = new VariableDeclaration(type, [ident], [init]); |
2063 set(v, begin); | |
2064 variable = new DeclarationStatement(v); | |
2065 set(variable, begin); | |
2034 } | 2066 } |
2035 else | 2067 else |
2036 condition = parseExpression(); | 2068 condition = parseExpression(); |
2037 } | 2069 } |
2038 require(T.RParen); | 2070 require(T.RParen); |
3753 nT(); | 3785 nT(); |
3754 set(t, begin); | 3786 set(t, begin); |
3755 break; | 3787 break; |
3756 case T.Identifier, T.Typeof, T.Dot: | 3788 case T.Identifier, T.Typeof, T.Dot: |
3757 t = parseDotListType(); | 3789 t = parseDotListType(); |
3790 assert(!isNodeSet(t)); | |
3791 set(t, begin); | |
3758 break; | 3792 break; |
3759 version(D2) | 3793 version(D2) |
3760 { | 3794 { |
3761 case T.Const: | 3795 case T.Const: |
3762 // const ( Type ) | 3796 // const ( Type ) |