()
| 1150 | |
| 1151 | // simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE |
| 1152 | private _parseSimpleStatement(): StatementListNode { |
| 1153 | let statement = new StatementListNode(this._peekToken()); |
| 1154 | |
| 1155 | while (true) { |
| 1156 | // Swallow invalid tokens to make sure we make forward progress. |
| 1157 | if (this._peekTokenType() === TokenType.Invalid) { |
| 1158 | const invalidToken = this._getNextToken(); |
| 1159 | const text = this._fileContents!.substr(invalidToken.start, invalidToken.length); |
| 1160 | this._addError(`Invalid token: "${ text }"`, invalidToken); |
| 1161 | this._consumeTokensUntilType(TokenType.NewLine); |
| 1162 | break; |
| 1163 | } |
| 1164 | |
| 1165 | let smallStatement = this._parseSmallStatement(); |
| 1166 | statement.statements.push(smallStatement); |
| 1167 | statement.extend(smallStatement); |
| 1168 | |
| 1169 | if (smallStatement instanceof ErrorExpressionNode) { |
| 1170 | // No need to log an error here. We assume that |
| 1171 | // it was already logged by _parseSmallStatement. |
| 1172 | break; |
| 1173 | } |
| 1174 | |
| 1175 | // Consume the semicolon if present. |
| 1176 | if (!this._consumeTokenIfType(TokenType.Semicolon)) { |
| 1177 | break; |
| 1178 | } |
| 1179 | |
| 1180 | let nextTokenType = this._peekTokenType(); |
| 1181 | if (nextTokenType === TokenType.NewLine || nextTokenType === TokenType.EndOfStream) { |
| 1182 | break; |
| 1183 | } |
| 1184 | } |
| 1185 | |
| 1186 | if (!this._consumeTokenIfType(TokenType.NewLine)) { |
| 1187 | this._addError('Statements must be separated by newlines or semicolons', |
| 1188 | this._peekToken()); |
| 1189 | } |
| 1190 | |
| 1191 | return statement; |
| 1192 | } |
| 1193 | |
| 1194 | // small_stmt: (expr_stmt | del_stmt | pass_stmt | flow_stmt | |
| 1195 | // import_stmt | global_stmt | nonlocal_stmt | assert_stmt) |
no test coverage detected