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.