postfix_evaluator.h revision fe82bf24a93d9d3affd614aaa23f2f018a733d8e
1// Copyright (C) 2006 Google Inc. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15// postfix_evaluator.h: Postfix (reverse Polish) notation expression evaluator. 16// 17// PostfixEvaluator evaluates an expression, using the expression itself 18// in postfix (reverse Polish) notation and a dictionary mapping constants 19// and variables to their values. The evaluator supports standard 20// arithmetic operations, assignment into variables, and when an optional 21// MemoryRange is provided, dereferencing. (Any unary key-to-value operation 22// may be used with a MemoryRange implementation that returns the appropriate 23// values, but PostfixEvaluator was written with dereferencing in mind.) 24// 25// The expression language is simple. Expressions are supplied as strings, 26// with operands and operators delimited by whitespace. Operands may be 27// either literal values suitable for ValueType, or constants or variables, 28// which reference the dictionary. The supported binary operators are + 29// (addition), - (subtraction), * (multiplication), / (quotient of division), 30// and % (modulus of division). The unary ^ (dereference) operator is also 31// provided. These operators allow any operand to be either a literal 32// value, constant, or variable. Assignment (=) of any type of operand into 33// a variable is also supported. 34// 35// The dictionary is provided as a map with string keys. Keys beginning 36// with the '$' character are treated as variables. All other keys are 37// treated as constants. Any results must be assigned into variables in the 38// dictionary. These variables do not need to exist prior to calling 39// Evaluate, unless used in an expression prior to being assigned to. The 40// internal stack state is not made available after evaluation, and any 41// values remaining on the stack are treated as evidence of incomplete 42// execution and cause the evaluator to indicate failure. 43// 44// PostfixEvaluator is intended to support evaluation of "program strings" 45// obtained from MSVC frame data debugging information in pdb files as 46// returned by the DIA APIs. 47// 48// Author: Mark Mentovai 49 50#ifndef PROCESSOR_POSTFIX_EVALUATOR_H__ 51#define PROCESSOR_POSTFIX_EVALUATOR_H__ 52 53 54#include <map> 55#include <string> 56#include <vector> 57 58namespace google_airbag { 59 60using std::map; 61using std::string; 62using std::vector; 63 64class MemoryRegion; 65 66template<typename ValueType> 67class PostfixEvaluator { 68 public: 69 typedef map<string, ValueType> DictionaryType; 70 typedef map<string, bool> DictionaryValidityType; 71 72 // Create a PostfixEvaluator object that may be used (with Evaluate) on 73 // one or more expressions. PostfixEvaluator does not take ownership of 74 // either argument. |memory| may be NULL, in which case dereferencing 75 // (^) will not be supported. |dictionary| may be NULL, but evaluation 76 // will fail in that case unless set_dictionary is used before calling 77 // Evaluate. 78 PostfixEvaluator(DictionaryType *dictionary, MemoryRegion *memory) 79 : dictionary_(dictionary), memory_(memory), stack_() {} 80 81 // Evaluate the expression. The results of execution will be stored 82 // in one (or more) variables in the dictionary. Returns false if any 83 // failures occure during execution, leaving variables in the dictionary 84 // in an indeterminate state. If assigned is non-NULL, any keys set in 85 // the dictionary as a result of evaluation will also be set to true in 86 // assigned, providing a way to determine if an expression modifies any 87 // of its input variables. 88 bool Evaluate(const string &expression, DictionaryValidityType *assigned); 89 90 DictionaryType* dictionary() const { return dictionary_; } 91 92 // Reset the dictionary. PostfixEvaluator does not take ownership. 93 void set_dictionary(DictionaryType *dictionary) {dictionary_ = dictionary; } 94 95 private: 96 // Return values for PopValueOrIdentifier 97 enum PopResult { 98 POP_RESULT_FAIL = 0, 99 POP_RESULT_VALUE, 100 POP_RESULT_IDENTIFIER 101 }; 102 103 // Retrieves the topmost literal value, constant, or variable from the 104 // stack. Returns POP_RESULT_VALUE if the topmost entry is a literal 105 // value, and sets |value| accordingly. Returns POP_RESULT_IDENTIFIER 106 // if the topmost entry is a constant or variable identifier, and sets 107 // |identifier| accordingly. Returns POP_RESULT_FAIL on failure, such 108 // as when the stack is empty. 109 PopResult PopValueOrIdentifier(ValueType *value, string *identifier); 110 111 // Retrieves the topmost value on the stack. If the topmost entry is 112 // an identifier, the dictionary is queried for the identifier's value. 113 // Returns false on failure, such as when the stack is empty or when 114 // a nonexistent identifier is named. 115 bool PopValue(ValueType *value); 116 117 // Retrieves the top two values on the stack, in the style of PopValue. 118 // value2 is popped before value1, so that value1 corresponds to the 119 // entry that was pushed prior to value2. Returns false on failure. 120 bool PopValues(ValueType *value1, ValueType *value2); 121 122 // Pushes a new value onto the stack. 123 void PushValue(const ValueType &value); 124 125 // The dictionary mapping constant and variable identifiers (strings) to 126 // values. Keys beginning with '$' are treated as variable names, and 127 // PostfixEvaluator is free to create and modify these keys. Weak pointer. 128 DictionaryType *dictionary_; 129 130 // If non-NULL, the MemoryRegion used for dereference (^) operations. 131 // If NULL, dereferencing is unsupported and will fail. Weak pointer. 132 MemoryRegion *memory_; 133 134 // The stack contains state information as execution progresses. Values 135 // are pushed on to it as the expression string is read and as operations 136 // yield values; values are popped when used as operands to operators. 137 vector<string> stack_; 138}; 139 140} // namespace google_airbag 141 142 143#endif // PROCESSOR_POSTFIX_EVALUATOR_H__ 144