TPParseTreeNode CFormulaParser::ParseOpenPPLRaiseByExpression() { // There are 3 possibilities // RAISE <Amount> FORCE // RAISE <PercentagedPot>% FORCE // // Keyword RAISE got already consumed TPParseTreeNode action = new CParseTreeNode(_tokenizer.LineRelative()); TPParseTreeNode expression; int _token_ID = _tokenizer.LookAhead(); if ((_token_ID == kTokenNumber) || (_token_ID == kTokenIdentifier) || TokenIsBracketOpen(_token_ID)){ expression = ParseExpression(); } else { CParseErrors::Error("Missing expression after keyword RaiseBy.\n" "Expecting the betsize in big blinds or a potsize-expression.\n" "Example: WHEN ... RAISEBY 60% FORCE\n"); return NULL; } _token_ID = _tokenizer.LookAhead(); if (_token_ID == kTokenOperatorPercentage) { // Percentaged Potsize _tokenizer.GetToken(); action->MakeRaiseByPercentagedPotsizeAction(expression); return action; } else { // Raise by N big blinds action->MakeRaiseByAction(expression); return action; } }
TPParseTreeNode CFormulaParser::ParseExpression() { int token_ID = _tokenizer.LookAhead(); TPParseTreeNode expression; // Handle brackets before unary, because brackets are also "unary" if (TokenIsBracketOpen(token_ID)) { expression = ParseBracketExpression(); } else if (TokenIsUnary(token_ID)) { expression = ParseUnaryExpression(); } else if ((token_ID == kTokenIdentifier) || (token_ID == kTokenNumber)) { expression = ParseSimpleExpression(); } else { CParseErrors::Error("Unexpected token inside expression.\n" "Expecting: opening bracket, unary operator, identifier or number.\n"); return NULL; } token_ID = _tokenizer.LookAhead(); if (TokenIsBinary(token_ID)) { _tokenizer.GetToken(); // Special handling of percentaged potsized bets, // that look like modulo or percentage operators, // but lack a 2nd operand and have "Force" instead. // When ... RaiseBy 60% Force if (token_ID == kTokenOperatorPercentage) { int next_token_ID = _tokenizer.LookAhead(); if (next_token_ID == kTokenKeywordForce) { // Now we should pushback the *2nd last* token (percentage) _tokenizer.PushBackAdditionalPercentageOperator(); // and return the expression we got so far return expression; } } TPParseTreeNode second_expression = ParseExpression(); TPParseTreeNode binary_node = new CParseTreeNode(_tokenizer.LineRelative()); binary_node->MakeBinaryOperator(token_ID, expression, second_expression); write_log(preferences.debug_parser(), "[FormulaParser] Binary node %i\n", binary_node); return binary_node; } else if (token_ID == kTokenOperatorConditionalIf) { // Ternary condition TPParseTreeNode then_expression; TPParseTreeNode else_expression; ParseConditionalPartialThenElseExpressions( &then_expression, &else_expression); TPParseTreeNode ternary_node = new CParseTreeNode(_tokenizer.LineRelative()); ternary_node->MakeTernaryOperator(token_ID, expression, then_expression, else_expression); write_log(preferences.debug_parser(), "[FormulaParser] Ternary node %i\n", ternary_node); return ternary_node; } else { // We got the complete expression // No complex binary or ternary condition write_log(preferences.debug_parser(), "[FormulaParser] Expression %i\n", expression); return expression; } }
TPParseTreeNode CFormulaParser::ParseBracketExpression() { // Bracket expressions, three different types () [] {} int opening_bracket = _tokenizer.GetToken(); assert(TokenIsBracketOpen(opening_bracket)); TPParseTreeNode expression = ParseExpression(); ExpectMatchingBracketClose(opening_bracket); TPParseTreeNode bracket_node = new CParseTreeNode(_tokenizer.LineRelative()); // Brackets get an unary node in the tree // This will lead to a simple way to handle precedence of operators. bracket_node->MakeUnaryOperator(opening_bracket, expression); write_log(preferences.debug_parser(), "[FormulaParser] Bracket node %i\n", bracket_node); return bracket_node; }
void CFormulaParser::ExpectMatchingBracketClose(int opening_bracket){ assert(TokenIsBracketOpen(opening_bracket)); int expected_bracket_close = _tokenizer.GetToken(); switch (opening_bracket) { case kTokenBracketOpen_1: if (expected_bracket_close == kTokenBracketClose_1) return; case kTokenBracketOpen_2: if (expected_bracket_close == kTokenBracketClose_2) return; case kTokenBracketOpen_3: if (expected_bracket_close == kTokenBracketClose_3) return; } CParseErrors::Error("Expecting a closing bracket\n" "(or bracket of another type).\n"); }
bool CParseTreeOperatorNode::EvaluatesToBinaryNumber() { if (TokenEvaluatesToBinaryNumber(_node_type)) { // Operation that evaluates to binary number, // e.g. bit-shift, logical and, etc. return true; } else if (TokenIsBracketOpen(_node_type)) { // Have a look at the sub-extreesopn TPParseTreeNode sub_expression = _first_sibbling; // There has to be an expresison inside the brackets assert (_first_sibbling != NULL); return _first_sibbling->EvaluatesToBinaryNumber(); } // Nothing binary return false; }
TPParseTreeNode CFormulaParser::ParseOpenPPLRaiseToExpression() { // RaiseTo N Force // Keyword RaiseTo got already consumed TPParseTreeNode action = new CParseTreeNode(_tokenizer.LineRelative()); TPParseTreeNode expression; int _token_ID = _tokenizer.LookAhead(); if ((_token_ID == kTokenNumber) || (_token_ID == kTokenIdentifier) || TokenIsBracketOpen(_token_ID)) { expression = ParseExpression(); } else { CParseErrors::Error("Missing expression after keyword RaiseTo.\n" "Expecting the betsize in big blinds.\n"); return NULL; } action->MakeRaiseToAction(expression); return action; }
void CFormulaParser::ErrorMissingAction(int token_ID) { CString error_message = "Missing action after when-condition\n"; if (token_ID == kTokenNumber) { error_message += "Found a number. Probably missing operator\n"; } else if (token_ID == TokenIsBracketOpen(token_ID)) { error_message += "Found a bracket. Probably missing operator\n"; } else if (token_ID == kTokenIdentifier) { CString name = _tokenizer.GetTokenString(); name.MakeLower(); if (name.Left(4) == "user") { error_message += "Found a user-variable.\n"; error_message += "Correct syntax: When <condition> Set user_xyz\n"; } else { error_message += "\nFound an identifier. Probably missing operator\n"; } } CParseErrors::Error(error_message); }
CString CParseTreeNode::Serialize() { if (_node_type == kTokenIdentifier) { return _terminal_name; } else if (_node_type == kTokenNumber) { return Number2CString(_constant_value); } else if (TokenIsBracketOpen(_node_type)) { return ("(" + _first_sibbling->Serialize() + ")"); } else if (TokenIsUnary(_node_type)) { assert(_first_sibbling != NULL); return TokenString(_node_type) + "(" + _first_sibbling->Serialize() + ")"; } else if (TokenIsBinary(_node_type)) { assert(_first_sibbling != NULL); assert(_second_sibbling != NULL); return "(" + _first_sibbling->Serialize() + " " + TokenString(_node_type) + " " + _second_sibbling->Serialize() + ")"; } else if (_node_type == kTokenOperatorConditionalIf) { assert(_first_sibbling != NULL); assert(_second_sibbling != NULL); assert(_third_sibbling != NULL); return "(" + _first_sibbling->Serialize() + " ? " + _second_sibbling->Serialize() + " : " + _third_sibbling->Serialize() + ")"; } else if (IsOpenEndedWhenCondition()) { return "WHEN: " + _first_sibbling->Serialize() + "\n" + (_second_sibbling? _second_sibbling->Serialize(): "") // No third sibbling to serialize, because this is the next open-ender // and TWO pointers point to it (one from a normal "when") + "WEND"; } else if (IsWhenConditionWithAction()) { return " WHEN: " + _first_sibbling->Serialize() + "WRETURN: " + (_second_sibbling? _second_sibbling->Serialize(): "") + "\n" // Third sibbling: either next when-condition or next open-ended when-condition + (_third_sibbling? _third_sibbling->Serialize(): ""); } else { // Unhandled note-type, probably new and therefore not yet handled write_log(k_always_log_errors, "[CParseTreeNode] ERROR: Unhandled node-tzpe %i in serialiyation of parse-tree\n", _node_type); return ""; } }