/// <summary>Reads a literal or sub-expression</summary> /// <param name="pos">Position of literal or first token of sub-expression</param> /// <returns>Expression tree</returns> /// <exception cref="Logic::AlgorithmException">Attempted to read incorrect type of Token</exception> /// <exception cref="Logic::ExpressionParserException">Syntax error</exception> /// <remarks>Advances the iterator to beyond the end of the literal or sub-expression</remarks> ExpressionParser::ExpressionTree ExpressionParser::ReadValue(TokenIterator& pos) { ExpressionTree expr = nullptr; // Rule: Value = Literal / '(' Expression ')' // Match: Literal if (MatchLiteral(pos)) return ExpressionTree( new LiteralValue(ReadLiteral(pos)) ); // Read: Bracket [nothrow] if (!MatchOperator(pos, L"(")) { // Failed: Unexpected EOF if (pos >= InputEnd) throw ExpressionParserException(HERE, --pos, L"Missing operand"); // Failed: Unexpected token throw ExpressionParserException(HERE, pos, VString(L"Unexpected '%s'", pos->Text.c_str())); } // Read: Expression (may throw) const ScriptToken& open = ReadOperator(pos); expr = ReadExpression(pos); // Adv. then match // Read: Bracket [nothrow] if (MatchOperator(pos, L")")) return ExpressionTree( new BracketedExpression(open, expr, ReadOperator(pos)) ); // Failure: Missing closing bracket if (pos >= InputEnd) throw ExpressionParserException(HERE, --pos, L"Missing closing bracket"); else throw ExpressionParserException(HERE, pos, L"Expected closing bracket"); }
/** * @brief Matches an OSC address pattern with a partial target OSC address that * has been truncated. * * Returns true if the OSC address pattern matches the partial target OSC * address. The target OSC address cannot contain any special characters: * '?', ' *', '[]', or '{}'. * * Matching to a partial OSC address can simplify the process of filtering * through multiple similar OSC address. For example, matching to the following * list would be quicker if an incoming message was first matched to either * "/inputs" and "/outputs". * - "/inputs/digital" * - "/inputs/analogue" * - "/inputs/serial" * - "/outputs/digital" * - "/outputs/pwm" * - "/outputs/serial" * * Example use: * @code * OscMessage oscMessage; * OscMessageInitialise(&oscMessage, "/example/oscAddress/pattern"); * if(OscAddressMatch(oscMessage.oscAddressPattern, "/example") == true) { * printf("Match!"); * } * @endcode * * @param oscAddressPattern OSC address pattern. * @param oscAddress Partial target OSC address. * @return true if the OSC address pattern matches the partial target OSC * oscAddress. */ bool OscAddressMatchPartial(const char * oscAddressPattern, const char * const oscAddress) { return MatchLiteral(oscAddressPattern, oscAddress, true); }
/** * @brief Matches an OSC address pattern with a target OSC address. * * Returns true if the OSC address pattern matches the target OSC address. The * target OSC address cannot contain any special characters: '?', ' *', '[]', or * '{}'. * * Example use: * @code * OscMessage oscMessage; * OscMessageInitialise(&oscMessage, "/example/oscAddress/pattern"); * if(OscAddressMatch(oscMessage.oscAddressPattern, "/example/oscAddress/pattern") == true) { * printf("Match!"); * } * @endcode * * @param oscAddressPattern OSC address pattern. * @param oscAddress Target OSC address. * @return true if the OSC address pattern and target oscAddress match. */ bool OscAddressMatch(const char * oscAddressPattern, const char * const oscAddress) { return MatchLiteral(oscAddressPattern, oscAddress, false); }