(minPrecedence, terminal, tuple)
| 1076 | return null; |
| 1077 | } |
| 1078 | _parseExpression(minPrecedence, terminal, tuple) { |
| 1079 | minPrecedence = minPrecedence || -1; |
| 1080 | const terminalSet = new Set(terminal); |
| 1081 | const stack = []; |
| 1082 | for (;;) { |
| 1083 | let position = this._position(); |
| 1084 | let node = null; |
| 1085 | const token = this._tokenizer.peek(); |
| 1086 | if (stack.length === 1 && terminalSet.has(token.value)) { |
| 1087 | break; |
| 1088 | } |
| 1089 | const precedence = ast._Parser._precedence[token.value]; |
| 1090 | if (precedence) { |
| 1091 | if (precedence >= minPrecedence) { |
| 1092 | this._tokenizer.read(); |
| 1093 | if (token.value === 'not' && this._tokenizer.accept('id', 'in')) { |
| 1094 | token.value = 'not in'; |
| 1095 | } else if (token.value === 'is' && this._tokenizer.accept('id', 'not')) { |
| 1096 | token.value = 'is not'; |
| 1097 | } |
| 1098 | if (stack.length > 0) { |
| 1099 | let op = null; |
| 1100 | switch (token.value) { |
| 1101 | case '+': op = new ast.Add(); break; |
| 1102 | case '-': op = new ast.Sub(); break; |
| 1103 | case '*': op = new ast.Mult(); break; |
| 1104 | case '/': op = new ast.Div(); break; |
| 1105 | case '//': op = new ast.FloorDiv(); break; |
| 1106 | case '**': op = new ast.Pow(); break; |
| 1107 | case '@': op = new ast.MatMult(); break; |
| 1108 | case '&': op = new ast.BitAnd(); break; |
| 1109 | case '^': op = new ast.BitXor(); break; |
| 1110 | case '|': op = new ast.BitOr(); break; |
| 1111 | case '%': op = new ast.Mod(); break; |
| 1112 | case '>>': op = new ast.RShift(); break; |
| 1113 | case '<<': op = new ast.LShift(); break; |
| 1114 | default: break; |
| 1115 | } |
| 1116 | if (op) { |
| 1117 | const left = stack.pop(); |
| 1118 | const right = this._parseExpression(precedence, terminal, tuple === true); |
| 1119 | node = new ast.BinOp(left, op, right); |
| 1120 | } else { |
| 1121 | switch (token.value) { |
| 1122 | case '==': op = new ast.Eq(); break; |
| 1123 | case '!=': op = new ast.NotEq(); break; |
| 1124 | case '>=': op = new ast.GtE(); break; |
| 1125 | case '<=': op = new ast.LtE(); break; |
| 1126 | case '<': op = new ast.Lt(); break; |
| 1127 | case '>': op = new ast.Gt(); break; |
| 1128 | case 'is': op = new ast.Is(); break; |
| 1129 | case 'is not': op = new ast.IsNot(); break; |
| 1130 | case 'in': op = new ast.In(); break; |
| 1131 | case 'not in': op = new ast.NotIn(); break; |
| 1132 | default: break; |
| 1133 | } |
| 1134 | const left = stack.pop(); |
| 1135 | const comparator = this._parseExpression(precedence, ['for', 'if'], tuple === true); |
no test coverage detected