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