|
|
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 1998, Microsoft Corp. All rights reserved.
//
// FILE
//
// xprparse.cpp
//
// SYNOPSIS
//
// This file implements the function IASParseExpression.
//
// MODIFICATION HISTORY
//
// 02/06/1998 Original version.
// 05/21/1999 Remove old style trace.
// 03/23/2000 Use two quotes to escape a quote.
//
///////////////////////////////////////////////////////////////////////////////
#include <ias.h>
#include <ExprBuilder.h>
#include <Parser.h>
#include <xprparse.h>
//////////
// Struct for converting an identifier to a logical token.
//////////
struct KeyWord { PCWSTR identifier; IAS_LOGICAL_TOKEN token; };
//////////
// Table of keywords. These must be sorted alphabetically.
//////////
const KeyWord KEYWORDS[] = { { L"AND", IAS_LOGICAL_AND }, { L"FALSE", IAS_LOGICAL_FALSE }, { L"NOT", IAS_LOGICAL_NOT }, { L"OR", IAS_LOGICAL_OR }, { L"TRUE", IAS_LOGICAL_TRUE }, { L"XOR", IAS_LOGICAL_XOR }, { NULL, IAS_LOGICAL_NUM_TOKENS } };
//////////
// Returns the IAS_LOGICAL_TOKEN equivalent for 'key' or IAS_LOGICAL_NUM_TOKENS
// if no such equivalent exists.
//////////
IAS_LOGICAL_TOKEN findKeyWord(PCWSTR key) throw () { // We'll use a linear search since the table is so small.
for (const KeyWord* i = KEYWORDS; i->identifier; ++i) { int cmp = _wcsicmp(key, i->identifier);
// Did we find it ?
if (cmp == 0) { return i->token; }
// Did we we go past it ?
if (cmp < 0) { break; } }
return IAS_LOGICAL_NUM_TOKENS; }
//////////
// Special characters for parsing.
//////////
const WCHAR WHITESPACE[] = L" \t\n"; const WCHAR TOKEN_DELIMITERS[] = L" \t\n()";
//////////
// Parse a chunk of expression text and add it to the ExpressionBuilder.
//////////
void addExpressionString(ExpressionBuilder& expression, PCWSTR szExpression) { //////////
// Make a local copy because parser can temporarily modify the string.
//////////
size_t len = sizeof(WCHAR) * (wcslen(szExpression) + 1); Parser p((PWSTR)memcpy(_alloca(len), szExpression, len));
//////////
// Loop through the expression until we hit the null-terminator.
//////////
while (*p.skip(WHITESPACE) != L'\0') { //////////
// Parentheses are handled separately since they don't have to be
// delimited by whitespace.
//////////
if (*p == L'(') { expression.addToken(IAS_LOGICAL_LEFT_PAREN); ++p; } else if (*p == L')') { expression.addToken(IAS_LOGICAL_RIGHT_PAREN); ++p; } else { // Get the next token.
const wchar_t* token = p.findToken(TOKEN_DELIMITERS);
// Check if it's a keyword.
IAS_LOGICAL_TOKEN keyWord = findKeyWord(token); if (keyWord != IAS_LOGICAL_NUM_TOKENS) { // If it is a keyword, add it to the expression ...
expression.addToken(keyWord); p.releaseToken(); } else { // If it's not a keyword, it must be a condition object.
expression.addCondition(token); p.releaseToken();
// Skip the leading parenthesis.
p.skip(WHITESPACE); p.ignore(L'(');
// Skip the leading quote.
p.skip(WHITESPACE); p.ignore(L'\"');
// We're now at the beginning of the condition text.
p.beginToken();
// Find the trailing quote, skipping any escaped characters.
while (p.findNext(L'\"')[1] == L'\"') { ++p; p.erase(1); }
// Add the condition text.
expression.addConditionText(p.endToken()); p.releaseToken();
// Skip the trailing quote
p.ignore(L'\"');
// Skip the trailing parenthesis.
p.skip(WHITESPACE); p.ignore(L')'); } } } }
HRESULT WINAPI IASParseExpression( PCWSTR szExpression, VARIANT* pVal ) { if (szExpression == NULL || pVal == NULL) { return E_INVALIDARG; }
VariantInit(pVal);
try { ExpressionBuilder expression;
addExpressionString(expression, szExpression);
expression.detach(pVal); } catch (Parser::ParseError) { return E_INVALIDARG; } CATCH_AND_RETURN()
return S_OK; }
HRESULT WINAPI IASParseExpressionEx( IN VARIANT* pvExpression, OUT VARIANT* pVal ) { if (pvExpression == NULL || pVal == NULL) { return E_INVALIDARG; }
// If the VARIANT contains a single BSTR, we can just use the method
// defined above.
if (V_VT(pvExpression) == VT_BSTR) { return IASParseExpression(V_BSTR(pvExpression), pVal); }
VariantInit(pVal);
try { ExpressionBuilder expression;
if (V_VT(pvExpression) == VT_EMPTY) { // If the variant is empty, the expression is always false.
expression.addToken(IAS_LOGICAL_FALSE); } else { CVariantVector<VARIANT> values(pvExpression);
for (size_t i = 0; i < values.size(); ++i) { // If we have more than one value, join them by AND's.
if (i != 0) { expression.addToken(IAS_LOGICAL_AND); }
if (V_VT(&values[i]) != VT_BSTR) { _com_issue_error(DISP_E_TYPEMISMATCH); }
addExpressionString(expression, V_BSTR(&values[i])); } }
expression.detach(pVal); } catch (Parser::ParseError) { return E_INVALIDARG; } CATCH_AND_RETURN()
return S_OK; }
|