Mercurial > projects > dil
comparison trunk/src/dil/parser/Parser.d @ 706:684ec5932b2e
Tidied up dil.parser.Parser.
author | Aziz K?ksal <aziz.koeksal@gmail.com> |
---|---|
date | Mon, 28 Jan 2008 21:39:08 +0100 |
parents | ff4643a4a97c |
children | 7917811f8116 |
comparison
equal
deleted
inserted
replaced
705:d75aad38d1b2 | 706:684ec5932b2e |
---|---|
17 import dil.Enums; | 17 import dil.Enums; |
18 import dil.CompilerInfo; | 18 import dil.CompilerInfo; |
19 import common; | 19 import common; |
20 | 20 |
21 /++ | 21 /++ |
22 The Parser produces a full parse tree by analyzing | 22 The Parser produces a full parse tree by examining |
23 the tokens of the provided source code. | 23 the list of tokens provided by the Lexer. |
24 +/ | 24 +/ |
25 class Parser | 25 class Parser |
26 { | 26 { |
27 Lexer lexer; | 27 Lexer lexer; /// Used to lex the source code. |
28 Token* token; /// Current non-whitespace token. | 28 Token* token; /// Current non-whitespace token. |
29 Token* prevToken; /// Previous non-whitespace token. | 29 Token* prevToken; /// Previous non-whitespace token. |
30 | 30 |
31 InfoManager infoMan; | 31 InfoManager infoMan; |
32 ParserError[] errors; | 32 ParserError[] errors; |
46 /++ | 46 /++ |
47 Construct a Parser object. | 47 Construct a Parser object. |
48 Params: | 48 Params: |
49 text = the UTF-8 source code. | 49 text = the UTF-8 source code. |
50 filePath = the path to the source code; used for error messages. | 50 filePath = the path to the source code; used for error messages. |
51 infoMan = used for collecting error messages. | |
51 +/ | 52 +/ |
52 this(char[] srcText, string filePath, InfoManager infoMan = null) | 53 this(char[] srcText, string filePath, InfoManager infoMan = null) |
53 { | 54 { |
54 this.infoMan = infoMan; | 55 this.infoMan = infoMan; |
55 lexer = new Lexer(srcText, filePath, infoMan); | 56 lexer = new Lexer(srcText, filePath, infoMan); |
56 } | 57 } |
57 | 58 |
59 /// Moves to the first token. | |
58 protected void init() | 60 protected void init() |
59 { | 61 { |
60 nT(); | 62 nT(); |
61 prevToken = token; | 63 prevToken = token; |
62 } | 64 } |
63 | 65 |
66 /// Moves to the next token. | |
64 void nT() | 67 void nT() |
65 { | 68 { |
66 prevToken = token; | 69 prevToken = token; |
67 do | 70 do |
68 { | 71 { |
69 lexer.nextToken(); | 72 lexer.nextToken(); |
70 token = lexer.token; | 73 token = lexer.token; |
71 } while (token.isWhitespace) // Skip whitespace | 74 } while (token.isWhitespace) // Skip whitespace |
72 } | 75 } |
73 | 76 |
74 /++ | 77 /// Start the parser and return the parsed Declarations. |
75 Start the parser and return the parsed Declarations. | |
76 +/ | |
77 CompoundDeclaration start() | 78 CompoundDeclaration start() |
78 { | 79 { |
79 init(); | 80 init(); |
80 auto begin = token; | 81 auto begin = token; |
81 auto decls = new CompoundDeclaration; | 82 auto decls = new CompoundDeclaration; |
84 decls.addOptChildren(parseDeclarationDefinitions()); | 85 decls.addOptChildren(parseDeclarationDefinitions()); |
85 set(decls, begin); | 86 set(decls, begin); |
86 return decls; | 87 return decls; |
87 } | 88 } |
88 | 89 |
89 /++ | 90 /// Start the parser and return the parsed Expression. |
90 Start the parser and return the parsed Expression. | |
91 +/ | |
92 Expression start2() | 91 Expression start2() |
93 { | 92 { |
94 init(); | 93 init(); |
95 return parseExpression(); | 94 return parseExpression(); |
96 } | 95 } |
97 | 96 |
98 uint trying; | 97 // Members related to the method try_(). |
99 uint errorCount; | 98 uint trying; /// Greater than 0 if Parser is in try_(). |
99 uint errorCount; /// Used to track nr. of errors while being in try_(). | |
100 | 100 |
101 /++ | 101 /++ |
102 This method executes the delegate parseMethod and when an error occurred | 102 This method executes the delegate parseMethod and when an error occurred |
103 the state of the lexer and parser are restored. | 103 the state of the lexer and parser are restored. |
104 +/ | 104 +/ |
105 ReturnType try_(ReturnType)(ReturnType delegate() parseMethod, out bool success) | 105 ReturnType try_(ReturnType)(ReturnType delegate() parseMethod, out bool success) |
106 { | 106 { |
107 // Save members. | |
107 auto oldToken = this.token; | 108 auto oldToken = this.token; |
108 auto oldPrevToken = this.prevToken; | 109 auto oldPrevToken = this.prevToken; |
109 auto oldCount = this.errorCount; | 110 auto oldCount = this.errorCount; |
110 | 111 |
111 ++trying; | 112 ++trying; |
112 auto result = parseMethod(); | 113 auto result = parseMethod(); |
113 --trying; | 114 --trying; |
114 // Check if an error occurred. | 115 // Check if an error occurred. |
115 if (errorCount != oldCount) | 116 if (errorCount != oldCount) |
116 { | 117 { // Restore members. |
117 // Restore members. | 118 token = oldToken; |
118 token = oldToken; | 119 prevToken = oldPrevToken; |
119 prevToken = oldPrevToken; | 120 lexer.token = oldToken; |
120 lexer.token = oldToken; | 121 errorCount = oldCount; |
121 errorCount = oldCount; | |
122 success = false; | 122 success = false; |
123 } | 123 } |
124 else | 124 else |
125 success = true; | 125 success = true; |
126 return result; | 126 return result; |
127 } | 127 } |
128 | 128 |
129 /++ | 129 /// Sets the begin and end tokens of a syntax tree node. |
130 Sets the begin and end tokens of an AST node. | |
131 +/ | |
132 Class set(Class)(Class node, Token* begin) | 130 Class set(Class)(Class node, Token* begin) |
133 { | 131 { |
134 node.setTokens(begin, this.prevToken); | 132 node.setTokens(begin, this.prevToken); |
135 return node; | 133 return node; |
136 } | 134 } |
137 | 135 |
138 /++ | 136 /// Returns true if set() has been called on a node. |
139 Returns true if set() has been called on a node. | 137 static bool isNodeSet(Node node) |
140 +/ | |
141 bool isNodeSet(Node node) | |
142 { | 138 { |
143 return node.begin !is null && node.end !is null; | 139 return node.begin !is null && node.end !is null; |
144 } | 140 } |
145 | 141 |
142 /// Returns the token kind of the next token. | |
146 TOK peekNext() | 143 TOK peekNext() |
147 { | 144 { |
148 Token* next = token; | 145 Token* next = token; |
149 do | 146 do |
150 lexer.peek(next); | 147 lexer.peek(next); |
151 while (next.isWhitespace) // Skip whitespace | 148 while (next.isWhitespace) // Skip whitespace |
152 return next.kind; | 149 return next.kind; |
153 } | 150 } |
154 | 151 |
152 /// Returns the token kind of the token after 'next'. | |
155 TOK peekAfter(ref Token* next) | 153 TOK peekAfter(ref Token* next) |
156 { | 154 { |
157 assert(next !is null); | 155 assert(next !is null); |
158 do | 156 do |
159 lexer.peek(next); | 157 lexer.peek(next); |
160 while (next.isWhitespace) // Skip whitespace | 158 while (next.isWhitespace) // Skip whitespace |
161 return next.kind; | 159 return next.kind; |
162 } | 160 } |
163 | 161 |
164 /// Skips the current token if its type matches tok and returns true. | 162 /// Skips the current token if it is of a certain kind and returns true. |
165 bool skipped()(TOK tok) // Templatized, so it's inlined. | 163 bool skipped()(TOK kind) // Templatized, so it's inlined. |
166 { | 164 { |
167 return token.kind == tok ? (nT(), true) : false; | 165 return token.kind == kind ? (nT(), true) : false; |
168 } | 166 } |
169 | 167 |
170 /++++++++++++++++++++++++++++++ | 168 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
171 + Declaration parsing methods + | 169 | Declaration parsing methods | |
172 ++++++++++++++++++++++++++++++/ | 170 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/ |
173 | 171 |
174 Declaration parseModuleDeclaration() | 172 Declaration parseModuleDeclaration() |
175 { | 173 { |
176 assert(token.kind == T.Module); | 174 assert(token.kind == T.Module); |
177 auto begin = token; | 175 auto begin = token; |
931 ModuleFQN[] moduleFQNs; | 929 ModuleFQN[] moduleFQNs; |
932 Identifier*[] moduleAliases; | 930 Identifier*[] moduleAliases; |
933 Identifier*[] bindNames; | 931 Identifier*[] bindNames; |
934 Identifier*[] bindAliases; | 932 Identifier*[] bindAliases; |
935 | 933 |
936 while (1) | 934 do |
937 { | 935 { |
938 ModuleFQN moduleFQN; | 936 ModuleFQN moduleFQN; |
939 Identifier* moduleAlias; | 937 Identifier* moduleAlias; |
940 | |
941 // AliasName = ModuleName | 938 // AliasName = ModuleName |
942 if (peekNext() == T.Assign) | 939 if (peekNext() == T.Assign) |
943 { | 940 { |
944 moduleAlias = requireIdentifier(MSG.ExpectedAliasModuleName); | 941 moduleAlias = requireIdentifier(MSG.ExpectedAliasModuleName); |
945 nT(); // Skip = | 942 nT(); // Skip = |
946 } | 943 } |
947 | 944 // Identifier ("." Identifier)* |
948 // Identifier(.Identifier)* | 945 do |
949 while (1) | |
950 { | |
951 moduleFQN ~= requireIdentifier(MSG.ExpectedModuleIdentifier); | 946 moduleFQN ~= requireIdentifier(MSG.ExpectedModuleIdentifier); |
952 if (token.kind != T.Dot) | 947 while (skipped(T.Dot)) |
953 break; | |
954 nT(); | |
955 } | |
956 | |
957 // Push identifiers. | 948 // Push identifiers. |
958 moduleFQNs ~= moduleFQN; | 949 moduleFQNs ~= moduleFQN; |
959 moduleAliases ~= moduleAlias; | 950 moduleAliases ~= moduleAlias; |
960 | 951 } while (skipped(T.Comma)) |
961 if (token.kind != T.Comma) | |
962 break; | |
963 nT(); | |
964 } | |
965 | 952 |
966 if (token.kind == T.Colon) | 953 if (token.kind == T.Colon) |
967 { | 954 { |
968 // BindAlias = BindName(, BindAlias = BindName)*; | 955 // BindAlias = BindName(, BindAlias = BindName)*; |
969 // BindName(, BindName)*; | 956 // BindName(, BindName)*; |
1384 mixin TemplateIdentifier !( TemplateArguments ) ; | 1371 mixin TemplateIdentifier !( TemplateArguments ) ; |
1385 mixin TemplateIdentifier !( TemplateArguments ) MixinIdentifier ; | 1372 mixin TemplateIdentifier !( TemplateArguments ) MixinIdentifier ; |
1386 +/ | 1373 +/ |
1387 Class parseMixin(Class)() | 1374 Class parseMixin(Class)() |
1388 { | 1375 { |
1376 static assert(is(Class == MixinDeclaration) || is(Class == MixinStatement)); | |
1389 assert(token.kind == T.Mixin); | 1377 assert(token.kind == T.Mixin); |
1390 nT(); // Skip mixin keyword. | 1378 nT(); // Skip mixin keyword. |
1391 | 1379 |
1392 static if (is(Class == MixinDeclaration)) | 1380 static if (is(Class == MixinDeclaration)) |
1393 { | 1381 { |
1416 require(T.Semicolon); | 1404 require(T.Semicolon); |
1417 | 1405 |
1418 return new Class(e, mixinIdent); | 1406 return new Class(e, mixinIdent); |
1419 } | 1407 } |
1420 | 1408 |
1421 /+++++++++++++++++++++++++++++ | 1409 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
1422 + Statement parsing methods + | 1410 | Statement parsing methods | |
1423 +++++++++++++++++++++++++++++/ | 1411 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/ |
1424 | 1412 |
1425 CompoundStatement parseStatements() | 1413 CompoundStatement parseStatements() |
1426 { | 1414 { |
1427 auto begin = token; | 1415 auto begin = token; |
1428 require(T.LBrace); | 1416 require(T.LBrace); |
1608 break; | 1596 break; |
1609 case T.Semicolon: | 1597 case T.Semicolon: |
1610 nT(); | 1598 nT(); |
1611 s = new EmptyStatement(); | 1599 s = new EmptyStatement(); |
1612 break; | 1600 break; |
1613 /+ | 1601 // Parse an ExpressionStatement: |
1614 Parse ExpressionStatement: | |
1615 +/ | |
1616 // Tokens that start a PrimaryExpression. | 1602 // Tokens that start a PrimaryExpression. |
1617 // case T.Identifier, T.Dot, T.Typeof: | 1603 // case T.Identifier, T.Dot, T.Typeof: |
1618 case T.This: | 1604 case T.This: |
1619 case T.Super: | 1605 case T.Super: |
1620 case T.Null: | 1606 case T.Null: |
1727 Statement parseAttributeStatement() | 1713 Statement parseAttributeStatement() |
1728 { | 1714 { |
1729 StorageClass stc, stc_tmp; | 1715 StorageClass stc, stc_tmp; |
1730 LinkageType prev_linkageType; | 1716 LinkageType prev_linkageType; |
1731 | 1717 |
1732 // Nested function. | 1718 Declaration parse() // Nested function. |
1733 Declaration parse() | |
1734 { | 1719 { |
1735 auto begin = token; | 1720 auto begin = token; |
1736 Declaration d; | 1721 Declaration d; |
1737 switch (token.kind) | 1722 switch (token.kind) |
1738 { | 1723 { |
2265 elseBody = parseNoScopeStatement(); | 2250 elseBody = parseNoScopeStatement(); |
2266 | 2251 |
2267 return new VersionStatement(cond, versionBody, elseBody); | 2252 return new VersionStatement(cond, versionBody, elseBody); |
2268 } | 2253 } |
2269 | 2254 |
2270 /+++++++++++++++++++++++++++++ | 2255 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
2271 + Assembler parsing methods + | 2256 | Assembler parsing methods | |
2272 +++++++++++++++++++++++++++++/ | 2257 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/ |
2273 | 2258 |
2274 Statement parseAsmBlockStatement() | 2259 Statement parseAsmBlockStatement() |
2275 { | 2260 { |
2276 assert(token.kind == T.Asm); | 2261 assert(token.kind == T.Asm); |
2277 nT(); // Skip asm keyword. | 2262 nT(); // Skip asm keyword. |
2297 goto LOpcode; | 2282 goto LOpcode; |
2298 case T.Identifier: | 2283 case T.Identifier: |
2299 ident = token.ident; | 2284 ident = token.ident; |
2300 nT(); // Skip Identifier | 2285 nT(); // Skip Identifier |
2301 if (skipped(T.Colon)) | 2286 if (skipped(T.Colon)) |
2302 { | 2287 { // Identifier : AsmStatement |
2303 // Identifier : AsmStatement | |
2304 s = new LabeledStatement(ident, parseAsmStatement()); | 2288 s = new LabeledStatement(ident, parseAsmStatement()); |
2305 break; | 2289 break; |
2306 } | 2290 } |
2307 | 2291 |
2308 LOpcode: | 2292 LOpcode: |
2707 } | 2691 } |
2708 set(e, begin); | 2692 set(e, begin); |
2709 return e; | 2693 return e; |
2710 } | 2694 } |
2711 | 2695 |
2712 /+++++++++++++++++++++++++++++ | 2696 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
2713 + Expression parsing methods + | 2697 | Expression parsing methods | |
2714 +++++++++++++++++++++++++++++/ | 2698 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/ |
2715 | 2699 |
2716 Expression parseExpression() | 2700 Expression parseExpression() |
2717 { | 2701 { |
2718 alias parseAssignExpression parseNext; | 2702 alias parseAssignExpression parseNext; |
2719 auto begin = token; | 2703 auto begin = token; |
3256 // DelegateLiteral := { Statements } | 3240 // DelegateLiteral := { Statements } |
3257 auto funcBody = parseFunctionBody(); | 3241 auto funcBody = parseFunctionBody(); |
3258 e = new FunctionLiteralExpression(funcBody); | 3242 e = new FunctionLiteralExpression(funcBody); |
3259 break; | 3243 break; |
3260 case T.Function, T.Delegate: | 3244 case T.Function, T.Delegate: |
3261 // FunctionLiteral := (function|delegate) Type? '(' ArgumentList ')' '{' Statements '}' | 3245 // FunctionLiteral := ("function"|"delegate") Type? "(" ArgumentList ")" FunctionBody |
3262 nT(); // Skip function|delegate token. | 3246 nT(); // Skip function or delegate keyword. |
3263 Type returnType; | 3247 Type returnType; |
3264 Parameters parameters; | 3248 Parameters parameters; |
3265 if (token.kind != T.LBrace) | 3249 if (token.kind != T.LBrace) |
3266 { | 3250 { |
3267 if (token.kind != T.LParen) // Optional return type | 3251 if (token.kind != T.LParen) // Optional return type |
3592 /// Parse the C-style array types after the declarator. | 3576 /// Parse the C-style array types after the declarator. |
3593 Type parseDeclaratorSuffix(Type lhsType) | 3577 Type parseDeclaratorSuffix(Type lhsType) |
3594 { | 3578 { |
3595 // The Type chain should be as follows: | 3579 // The Type chain should be as follows: |
3596 // int[3]* Identifier [][32] | 3580 // int[3]* Identifier [][32] |
3597 // <- <- -> -. | 3581 // <- <- -> -. |
3598 // ^------------------´ | 3582 // ^-----------------´ |
3599 // Resulting chain: [][32]*[3]int | 3583 // Resulting chain: [][32]*[3]int |
3600 Type parseNext() // Nested function required to accomplish this. | 3584 Type parseNext() // Nested function required to accomplish this. |
3601 { | 3585 { |
3602 if (token.kind != T.LBracket) | 3586 if (token.kind != T.LBracket) |
3603 return lhsType; // Break recursion; return Type on the left hand side of the Identifier. | 3587 return lhsType; // Break recursion; return Type on the left hand side of the Identifier. |