(tokens: SplootNode[], currentIndex: number, minPrecedence: number)
| 252 | } |
| 253 | |
| 254 | function parseExpression(tokens: SplootNode[], currentIndex: number, minPrecedence: number): [boolean, number] { |
| 255 | if (currentIndex >= tokens.length) { |
| 256 | // Ran out of tokens |
| 257 | return [true, currentIndex] |
| 258 | } |
| 259 | |
| 260 | let lookahead = tokens[currentIndex] |
| 261 | while ( |
| 262 | lookahead && |
| 263 | lookahead.type === 'PYTHON_BINARY_OPERATOR' && |
| 264 | BinaryOperators[(lookahead as PythonBinaryOperator).getOperator()] && |
| 265 | BinaryOperators[(lookahead as PythonBinaryOperator).getOperator()].precedence >= minPrecedence |
| 266 | ) { |
| 267 | const operator = (lookahead as PythonBinaryOperator).getOperator() |
| 268 | const precedence = BinaryOperators[operator].precedence |
| 269 | currentIndex += 1 |
| 270 | let valid = false |
| 271 | ;[valid, currentIndex] = parseLeaf(tokens, currentIndex) |
| 272 | if (!valid) { |
| 273 | // Leaf RHS was invalid |
| 274 | return [false, currentIndex] |
| 275 | } |
| 276 | if (currentIndex === tokens.length) { |
| 277 | return [true, currentIndex] |
| 278 | } |
| 279 | |
| 280 | lookahead = tokens[currentIndex] |
| 281 | while ( |
| 282 | lookahead && |
| 283 | lookahead.type === 'PYTHON_BINARY_OPERATOR' && |
| 284 | BinaryOperators[(lookahead as PythonBinaryOperator).getOperator()] && |
| 285 | BinaryOperators[(lookahead as PythonBinaryOperator).getOperator()].precedence > precedence |
| 286 | ) { |
| 287 | const secondOp = (lookahead as PythonBinaryOperator).getOperator() |
| 288 | const secondPrecedence = BinaryOperators[secondOp].precedence |
| 289 | let exprValid = false |
| 290 | ;[exprValid, currentIndex] = parseExpression(tokens, currentIndex, secondPrecedence) |
| 291 | if (!exprValid) { |
| 292 | // Invalid secondary parse |
| 293 | return [false, currentIndex] |
| 294 | } |
| 295 | if (currentIndex < tokens.length) { |
| 296 | lookahead = tokens[currentIndex] |
| 297 | } else { |
| 298 | lookahead = null |
| 299 | } |
| 300 | } |
| 301 | } |
| 302 | // Have parsed all valid operators |
| 303 | return [true, currentIndex] |
| 304 | } |
| 305 | |
| 306 | export function validateExpressionParse(tokens: SplootNode[]): [boolean, number] { |
| 307 | const [valid, index] = parseLeaf(tokens, 0) |
no test coverage detected