OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
11 // with the distribution. | 11 // with the distribution. |
(...skipping 23 matching lines...) Expand all Loading... |
35 #include "func-name-inferrer.h" | 35 #include "func-name-inferrer.h" |
36 #include "messages.h" | 36 #include "messages.h" |
37 #include "parser.h" | 37 #include "parser.h" |
38 #include "platform.h" | 38 #include "platform.h" |
39 #include "preparser.h" | 39 #include "preparser.h" |
40 #include "runtime.h" | 40 #include "runtime.h" |
41 #include "scopeinfo.h" | 41 #include "scopeinfo.h" |
42 #include "string-stream.h" | 42 #include "string-stream.h" |
43 | 43 |
44 #include "ast-inl.h" | 44 #include "ast-inl.h" |
45 #include "jump-target-inl.h" | |
46 | 45 |
47 namespace v8 { | 46 namespace v8 { |
48 namespace internal { | 47 namespace internal { |
49 | 48 |
50 // PositionStack is used for on-stack allocation of token positions for | 49 // PositionStack is used for on-stack allocation of token positions for |
51 // new expressions. Please look at ParseNewExpression. | 50 // new expressions. Please look at ParseNewExpression. |
52 | 51 |
53 class PositionStack { | 52 class PositionStack { |
54 public: | 53 public: |
55 explicit PositionStack(bool* ok) : top_(NULL), ok_(ok) {} | 54 explicit PositionStack(bool* ok) : top_(NULL), ok_(ok) {} |
(...skipping 1846 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1902 ExpectSemicolon(CHECK_OK); | 1901 ExpectSemicolon(CHECK_OK); |
1903 return new(zone()) ReturnStatement(expr); | 1902 return new(zone()) ReturnStatement(expr); |
1904 } | 1903 } |
1905 | 1904 |
1906 | 1905 |
1907 Block* Parser::WithHelper(Expression* obj, | 1906 Block* Parser::WithHelper(Expression* obj, |
1908 ZoneStringList* labels, | 1907 ZoneStringList* labels, |
1909 bool is_catch_block, | 1908 bool is_catch_block, |
1910 bool* ok) { | 1909 bool* ok) { |
1911 // Parse the statement and collect escaping labels. | 1910 // Parse the statement and collect escaping labels. |
1912 ZoneList<BreakTarget*>* target_list = new ZoneList<BreakTarget*>(0); | 1911 ZoneList<Label*>* target_list = new ZoneList<Label*>(0); |
1913 TargetCollector collector(target_list); | 1912 TargetCollector collector(target_list); |
1914 Statement* stat; | 1913 Statement* stat; |
1915 { Target target(&this->target_stack_, &collector); | 1914 { Target target(&this->target_stack_, &collector); |
1916 with_nesting_level_++; | 1915 with_nesting_level_++; |
1917 top_scope_->RecordWithStatement(); | 1916 top_scope_->RecordWithStatement(); |
1918 stat = ParseStatement(labels, CHECK_OK); | 1917 stat = ParseStatement(labels, CHECK_OK); |
1919 with_nesting_level_--; | 1918 with_nesting_level_--; |
1920 } | 1919 } |
1921 // Create resulting block with two statements. | 1920 // Create resulting block with two statements. |
1922 // 1: Evaluate the with expression. | 1921 // 1: Evaluate the with expression. |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2048 // 'try' Block Catch Finally | 2047 // 'try' Block Catch Finally |
2049 // | 2048 // |
2050 // Catch :: | 2049 // Catch :: |
2051 // 'catch' '(' Identifier ')' Block | 2050 // 'catch' '(' Identifier ')' Block |
2052 // | 2051 // |
2053 // Finally :: | 2052 // Finally :: |
2054 // 'finally' Block | 2053 // 'finally' Block |
2055 | 2054 |
2056 Expect(Token::TRY, CHECK_OK); | 2055 Expect(Token::TRY, CHECK_OK); |
2057 | 2056 |
2058 ZoneList<BreakTarget*>* target_list = new ZoneList<BreakTarget*>(0); | 2057 ZoneList<Label*>* target_list = new ZoneList<Label*>(0); |
2059 TargetCollector collector(target_list); | 2058 TargetCollector collector(target_list); |
2060 Block* try_block; | 2059 Block* try_block; |
2061 | 2060 |
2062 { Target target(&this->target_stack_, &collector); | 2061 { Target target(&this->target_stack_, &collector); |
2063 try_block = ParseBlock(NULL, CHECK_OK); | 2062 try_block = ParseBlock(NULL, CHECK_OK); |
2064 } | 2063 } |
2065 | 2064 |
2066 Block* catch_block = NULL; | 2065 Block* catch_block = NULL; |
2067 Variable* catch_var = NULL; | 2066 Variable* catch_var = NULL; |
2068 Block* finally_block = NULL; | 2067 Block* finally_block = NULL; |
2069 | 2068 |
2070 Token::Value tok = peek(); | 2069 Token::Value tok = peek(); |
2071 if (tok != Token::CATCH && tok != Token::FINALLY) { | 2070 if (tok != Token::CATCH && tok != Token::FINALLY) { |
2072 ReportMessage("no_catch_or_finally", Vector<const char*>::empty()); | 2071 ReportMessage("no_catch_or_finally", Vector<const char*>::empty()); |
2073 *ok = false; | 2072 *ok = false; |
2074 return NULL; | 2073 return NULL; |
2075 } | 2074 } |
2076 | 2075 |
2077 // If we can break out from the catch block and there is a finally block, | 2076 // If we can break out from the catch block and there is a finally block, |
2078 // then we will need to collect jump targets from the catch block. Since | 2077 // then we will need to collect jump targets from the catch block. Since |
2079 // we don't know yet if there will be a finally block, we always collect | 2078 // we don't know yet if there will be a finally block, we always collect |
2080 // the jump targets. | 2079 // the jump targets. |
2081 ZoneList<BreakTarget*>* catch_target_list = new ZoneList<BreakTarget*>(0); | 2080 ZoneList<Label*>* catch_target_list = new ZoneList<Label*>(0); |
2082 TargetCollector catch_collector(catch_target_list); | 2081 TargetCollector catch_collector(catch_target_list); |
2083 bool has_catch = false; | 2082 bool has_catch = false; |
2084 if (tok == Token::CATCH) { | 2083 if (tok == Token::CATCH) { |
2085 has_catch = true; | 2084 has_catch = true; |
2086 Consume(Token::CATCH); | 2085 Consume(Token::CATCH); |
2087 | 2086 |
2088 Expect(Token::LPAREN, CHECK_OK); | 2087 Expect(Token::LPAREN, CHECK_OK); |
2089 Handle<String> name = ParseIdentifier(CHECK_OK); | 2088 Handle<String> name = ParseIdentifier(CHECK_OK); |
2090 | 2089 |
2091 if (top_scope_->is_strict_mode() && IsEvalOrArguments(name)) { | 2090 if (top_scope_->is_strict_mode() && IsEvalOrArguments(name)) { |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2171 Statement* body = ParseStatement(NULL, CHECK_OK); | 2170 Statement* body = ParseStatement(NULL, CHECK_OK); |
2172 Expect(Token::WHILE, CHECK_OK); | 2171 Expect(Token::WHILE, CHECK_OK); |
2173 Expect(Token::LPAREN, CHECK_OK); | 2172 Expect(Token::LPAREN, CHECK_OK); |
2174 | 2173 |
2175 if (loop != NULL) { | 2174 if (loop != NULL) { |
2176 int position = scanner().location().beg_pos; | 2175 int position = scanner().location().beg_pos; |
2177 loop->set_condition_position(position); | 2176 loop->set_condition_position(position); |
2178 } | 2177 } |
2179 | 2178 |
2180 Expression* cond = ParseExpression(true, CHECK_OK); | 2179 Expression* cond = ParseExpression(true, CHECK_OK); |
2181 if (cond != NULL) cond->set_is_loop_condition(true); | |
2182 Expect(Token::RPAREN, CHECK_OK); | 2180 Expect(Token::RPAREN, CHECK_OK); |
2183 | 2181 |
2184 // Allow do-statements to be terminated with and without | 2182 // Allow do-statements to be terminated with and without |
2185 // semi-colons. This allows code such as 'do;while(0)return' to | 2183 // semi-colons. This allows code such as 'do;while(0)return' to |
2186 // parse, which would not be the case if we had used the | 2184 // parse, which would not be the case if we had used the |
2187 // ExpectSemicolon() functionality here. | 2185 // ExpectSemicolon() functionality here. |
2188 if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON); | 2186 if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON); |
2189 | 2187 |
2190 if (loop != NULL) loop->Initialize(cond, body); | 2188 if (loop != NULL) loop->Initialize(cond, body); |
2191 return loop; | 2189 return loop; |
2192 } | 2190 } |
2193 | 2191 |
2194 | 2192 |
2195 WhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) { | 2193 WhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) { |
2196 // WhileStatement :: | 2194 // WhileStatement :: |
2197 // 'while' '(' Expression ')' Statement | 2195 // 'while' '(' Expression ')' Statement |
2198 | 2196 |
2199 lexical_scope_->AddLoop(); | 2197 lexical_scope_->AddLoop(); |
2200 WhileStatement* loop = new(zone()) WhileStatement(labels); | 2198 WhileStatement* loop = new(zone()) WhileStatement(labels); |
2201 Target target(&this->target_stack_, loop); | 2199 Target target(&this->target_stack_, loop); |
2202 | 2200 |
2203 Expect(Token::WHILE, CHECK_OK); | 2201 Expect(Token::WHILE, CHECK_OK); |
2204 Expect(Token::LPAREN, CHECK_OK); | 2202 Expect(Token::LPAREN, CHECK_OK); |
2205 Expression* cond = ParseExpression(true, CHECK_OK); | 2203 Expression* cond = ParseExpression(true, CHECK_OK); |
2206 if (cond != NULL) cond->set_is_loop_condition(true); | |
2207 Expect(Token::RPAREN, CHECK_OK); | 2204 Expect(Token::RPAREN, CHECK_OK); |
2208 Statement* body = ParseStatement(NULL, CHECK_OK); | 2205 Statement* body = ParseStatement(NULL, CHECK_OK); |
2209 | 2206 |
2210 if (loop != NULL) loop->Initialize(cond, body); | 2207 if (loop != NULL) loop->Initialize(cond, body); |
2211 return loop; | 2208 return loop; |
2212 } | 2209 } |
2213 | 2210 |
2214 | 2211 |
2215 Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { | 2212 Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { |
2216 // ForStatement :: | 2213 // ForStatement :: |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2278 // Standard 'for' loop | 2275 // Standard 'for' loop |
2279 ForStatement* loop = new(zone()) ForStatement(labels); | 2276 ForStatement* loop = new(zone()) ForStatement(labels); |
2280 Target target(&this->target_stack_, loop); | 2277 Target target(&this->target_stack_, loop); |
2281 | 2278 |
2282 // Parsed initializer at this point. | 2279 // Parsed initializer at this point. |
2283 Expect(Token::SEMICOLON, CHECK_OK); | 2280 Expect(Token::SEMICOLON, CHECK_OK); |
2284 | 2281 |
2285 Expression* cond = NULL; | 2282 Expression* cond = NULL; |
2286 if (peek() != Token::SEMICOLON) { | 2283 if (peek() != Token::SEMICOLON) { |
2287 cond = ParseExpression(true, CHECK_OK); | 2284 cond = ParseExpression(true, CHECK_OK); |
2288 if (cond != NULL) cond->set_is_loop_condition(true); | |
2289 } | 2285 } |
2290 Expect(Token::SEMICOLON, CHECK_OK); | 2286 Expect(Token::SEMICOLON, CHECK_OK); |
2291 | 2287 |
2292 Statement* next = NULL; | 2288 Statement* next = NULL; |
2293 if (peek() != Token::RPAREN) { | 2289 if (peek() != Token::RPAREN) { |
2294 Expression* exp = ParseExpression(true, CHECK_OK); | 2290 Expression* exp = ParseExpression(true, CHECK_OK); |
2295 next = new(zone()) ExpressionStatement(exp); | 2291 next = new(zone()) ExpressionStatement(exp); |
2296 } | 2292 } |
2297 Expect(Token::RPAREN, CHECK_OK); | 2293 Expect(Token::RPAREN, CHECK_OK); |
2298 | 2294 |
(...skipping 1639 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3938 ASSERT(stat->is_target_for_anonymous()); | 3934 ASSERT(stat->is_target_for_anonymous()); |
3939 if (anonymous || ContainsLabel(stat->labels(), label)) { | 3935 if (anonymous || ContainsLabel(stat->labels(), label)) { |
3940 RegisterTargetUse(stat->continue_target(), t->previous()); | 3936 RegisterTargetUse(stat->continue_target(), t->previous()); |
3941 return stat; | 3937 return stat; |
3942 } | 3938 } |
3943 } | 3939 } |
3944 return NULL; | 3940 return NULL; |
3945 } | 3941 } |
3946 | 3942 |
3947 | 3943 |
3948 void Parser::RegisterTargetUse(BreakTarget* target, Target* stop) { | 3944 void Parser::RegisterTargetUse(Label* target, Target* stop) { |
3949 // Register that a break target found at the given stop in the | 3945 // Register that a break target found at the given stop in the |
3950 // target stack has been used from the top of the target stack. Add | 3946 // target stack has been used from the top of the target stack. Add |
3951 // the break target to any TargetCollectors passed on the stack. | 3947 // the break target to any TargetCollectors passed on the stack. |
3952 for (Target* t = target_stack_; t != stop; t = t->previous()) { | 3948 for (Target* t = target_stack_; t != stop; t = t->previous()) { |
3953 TargetCollector* collector = t->node()->AsTargetCollector(); | 3949 TargetCollector* collector = t->node()->AsTargetCollector(); |
3954 if (collector != NULL) collector->AddTarget(target); | 3950 if (collector != NULL) collector->AddTarget(target); |
3955 } | 3951 } |
3956 } | 3952 } |
3957 | 3953 |
3958 | 3954 |
(...skipping 1200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5159 info->is_global(), | 5155 info->is_global(), |
5160 info->StrictMode()); | 5156 info->StrictMode()); |
5161 } | 5157 } |
5162 } | 5158 } |
5163 | 5159 |
5164 info->SetFunction(result); | 5160 info->SetFunction(result); |
5165 return (result != NULL); | 5161 return (result != NULL); |
5166 } | 5162 } |
5167 | 5163 |
5168 } } // namespace v8::internal | 5164 } } // namespace v8::internal |
OLD | NEW |