coan  6.0.1
A C/C++ Configuration Analyzer
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
expression_parser.h
Go to the documentation of this file.
1 #ifndef EXPRESSION_PARSER_H
2 #define EXPRESSION_PARSER_H
3 #pragma once
4 /***************************************************************************
5  * Copyright (C) 2007-2013 Mike Kinghan, imk@burroingroingjoing.com *
6  * All rights reserved. *
7  * *
8  * Contributed originally by Mike Kinghan, imk@burroingroingjoing.com *
9  * *
10  * Redistribution and use in source and binary forms, with or without *
11  * modification, are permitted provided that the following conditions *
12  * are met: *
13  * *
14  * Redistributions of source code must retain the above copyright *
15  * notice, this list of conditions and the following disclaimer. *
16  * *
17  * Redistributions in binary form must reproduce the above copyright *
18  * notice, this list of conditions and the following disclaimer in the *
19  * documentation and/or other materials provided with the distribution. *
20  * *
21  * Neither the name of Mike Kinghan nor the names of its contributors *
22  * may be used to endorse or promote products derived from this software *
23  * without specific prior written permission. *
24  * *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
26  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *
27  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *
28  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *
29  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *
30  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *
31  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS *
32  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED *
33  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,*
34  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF *
35  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
36  * DAMAGE. *
37  * *
38  **************************************************************************/
39 #include "chew.h"
40 #include "evaluation.h"
41 #include <string>
42 #include <vector>
43 
48 // Forward decl
49 struct diagnostic_base;
50 struct reference;
51 
59 template<class CharSeq>
61 {
63 
65  using sequence_type = CharSeq;
71  non_paren = 1,
74  };
75 
77  enum precedence {
78  max = 10,
79  ternary_either_or = 10,
80  ternary_if = 10,
81  comma = 9,
82  boolean_or = 8,
83  boolean_and = 7,
84  bit_or = 6,
85  bit_xor = 6,
86  bit_and = 6,
87  eq = 5,
88  neq = 5,
89  le = 4,
90  ge = 4,
91  lt = 4,
92  gt = 4,
93  lshift = 3,
94  rshift = 3,
95  add = 2,
96  subtract = 2,
97  mult = 1,
98  divide = 1,
99  mod = 1,
100  };
101 
112  chewer<sequence_type> & chew,
113  reference const * ref = nullptr)
114  : _ternary_cond_stack(0),_seq(chew.buf()),
115  _start(chew),_cuts(0),_last_deletion(-1),_ref(ref) {
116  parse(chew);
117  }
118 
128  sequence_type & seq,
129  reference const * ref = nullptr,
130  size_t start = 0);
131 
135  evaluation result() const {
136  return _eval;
137  }
138 
140  explicit operator evaluation () const {
141  return result();
142  }
143 
149  std::string simplified() const;
150 
152  bool is_simplified() const {
153  return _cuts != 0;
154  }
155 
156 private:
157 
159  using infix_operation =
161 
163  evaluation op_lt(evaluation const & lhs, evaluation const & rhs) {
164  return evaluation(lhs.value() < rhs.value());
165  }
166 
168  evaluation op_gt(evaluation const & lhs, evaluation const & rhs) {
169  return evaluation(lhs.value() > rhs.value());
170  }
171 
173  evaluation op_le(evaluation const & lhs, evaluation const & rhs) {
174  return evaluation(lhs.value() <= rhs.value());
175  }
176 
178  evaluation op_ge(evaluation const & lhs, evaluation const & rhs) {
179  return evaluation(lhs.value() >= rhs.value());
180  }
181 
183  evaluation op_eq(evaluation const & lhs, evaluation const & rhs) {
184  return evaluation(lhs.value() == rhs.value());
185  }
186 
188  evaluation op_ne(evaluation const & lhs, evaluation const & rhs) {
189  return evaluation(lhs.value() != rhs.value());
190  }
191 
193  evaluation op_or(evaluation const & lhs, evaluation const & rhs);
194 
196  evaluation op_and(evaluation const & lhs, evaluation const & rhs);
197 
199  evaluation
200  op_ternary_if(evaluation const & lhs, evaluation const & rhs) {
201  _ternary_cond_stack.push_back(lhs);
202  return rhs;
203  }
204 
211  evaluation const & rhs);
212 
214  evaluation
215  op_bit_and(evaluation const & lhs, evaluation const & rhs) {
216  return evaluation(lhs.value() & rhs.value());
217  }
218 
220  evaluation
221  op_bit_or(evaluation const & lhs, evaluation const & rhs) {
222  return evaluation(lhs.value() | rhs.value());
223  }
224 
226  evaluation
227  op_bit_xor(evaluation const & lhs, evaluation const & rhs) {
228  return evaluation(lhs.value() ^ rhs.value());
229  }
230 
232  evaluation
233  op_lshift(evaluation const & lhs, evaluation const & rhs) {
234  return evaluation(lhs.value() << rhs.value());
235  }
236 
238  evaluation
239  op_rshift(evaluation const & lhs, evaluation const & rhs) {
240  return evaluation(lhs.value() >> rhs.value());
241  }
242 
244  evaluation op_add(evaluation const & lhs, evaluation const & rhs) {
245  return evaluation(lhs.value() + rhs.value());
246  }
247 
249  evaluation
250  op_subtract(evaluation const & lhs, evaluation const & rhs) {
251  return evaluation(lhs.value() - rhs.value());
252  }
253 
255  evaluation
256  op_comma(evaluation const & lhs, evaluation const & rhs) {
257  return rhs;
258  }
259 
261  evaluation op_mult(evaluation const & lhs, evaluation const & rhs) {
262  return evaluation(lhs.value() * rhs.value());
263  }
264 
266  evaluation op_divide(evaluation const & lhs, evaluation const & rhs);
267 
269  evaluation op_mod(evaluation const & lhs, evaluation const & rhs);
270 
278  void parse(chewer<sequence_type> & chew);
279 
292  evaluation
293  unary_op(chewer<sequence_type> & chew, size_t end);
294 
313  template<unsigned Precedence>
314  evaluation
315  infix_op(chewer<sequence_type> & chew, size_t end);
316 
318 
321  template<unsigned Precedence>
322  typename std::enable_if<(Precedence == 0),evaluation>::type
323  next_evaluator(chewer<sequence_type> & chew, size_t end) {
324  return unary_op(chew,end);
325  }
326 
327  template<unsigned Precedence>
328  typename std::enable_if<(Precedence > 0),evaluation>::type
329  next_evaluator(chewer<sequence_type> & chew, size_t end) {
330  return infix_op<Precedence>(chew,end);
331  }
333 
334 
342 
361  template<unsigned Precedence>
362  std::pair<expression_parser::infix_operation,bool>
364  size_t end,
365  size_t & op_start,
366  size_t & op_end);
367 
369  void delete_paren(size_t loff, size_t roff) {
370  _deletions.resize(_seq.size(), deletion_code::not_deleted);
371  _deletions[loff] = deletion_code::paren;
372  _deletions[roff] = deletion_code::paren;
373  if (ptrdiff_t(roff) > _last_deletion) {
374  _last_deletion = roff;
375  }
376  }
377 
379  void restore_paren(size_t loff, size_t roff) {
380  if (_deletions.size() > roff) {
381  _deletions[loff] = deletion_code::not_deleted;
382  _deletions[roff] = deletion_code::not_deleted;
383  }
384  for( ;_last_deletion >= 0 &&
385  _deletions[_last_deletion] == deletion_code::not_deleted;
386  --_last_deletion){}
387  }
388 
390  void restore_paren() {
391  for (ptrdiff_t i = _start; i <= _last_deletion; ++i) {
392  if (_deletions[i] == deletion_code::paren) {
393  _deletions[i] = deletion_code::not_deleted;
394  }
395  }
396  }
397 
412  void cut(size_t start, size_t end) {
413  _deletions.resize(_seq.size(),deletion_code::not_deleted);
414  for ( ;start < end; ++start) {
415  _deletions[start] = deletion_code::non_paren;
416  }
417  if (ptrdiff_t(end) > _last_deletion) {
418  _last_deletion = end;
419  }
420  ++_cuts;
421  }
422 
426  void defer_diagnostic(diagnostic_base & gripe);
427 
431  std::vector<evaluation> _ternary_cond_stack;
435  std::vector<deletion_code> _deletions;
437  size_t _start;
439  size_t _cuts;
441  ptrdiff_t _last_deletion;
445  reference const * _ref;
446 };
447 
448 #endif /* EOF*/
evaluation op_bit_and(evaluation const &lhs, evaluation const &rhs)
Bitwise AND operator.
template struct traits::is_random_access_char_sequence<T> exports a static const boolean member value...
Definition: traits.h:166
std::vector< deletion_code > _deletions
Vector of logical deletion codes;.
evaluation op_rshift(evaluation const &lhs, evaluation const &rhs)
Right-shift operator.
Not logically deleted.
evaluation apply(infix_operation op, evaluation &lhs, evaluation &rhs)
Apply a infix operation to arguments.
integer const & value() const
Get the integral value of the expression.
Definition: evaluation.h:98
evaluation op_add(evaluation const &lhs, evaluation const &rhs)
Addition operator.
evaluation op_lt(evaluation const &lhs, evaluation const &rhs)
Less-than operator.
std::string simplified() const
Get the most simplified form of the expression.
ptrdiff_t _last_deletion
Index of rightmost deletion, -1 if none.
evaluation op_ne(evaluation const &lhs, evaluation const &rhs)
Inequality operator.
evaluation op_lshift(evaluation const &lhs, evaluation const &rhs)
Left-shift operator.
size_t _cuts
Number of logically deleted operands.
evaluation op_subtract(evaluation const &lhs, evaluation const &rhs)
Subtraction operator.
void defer_diagnostic(diagnostic_base &gripe)
Defer a diagnostic, with the current line context appended if a source line is being parsed...
Encapsulates parsing of preprocessor expressions.
CharSeq sequence_type
Type of character-sequence containing the parsed expression.
A base class for diagnostic classes.
Definition: diagnostic.h:85
void delete_paren(size_t loff, size_t roff)
Logically delete redundant parentheses.
evaluation op_le(evaluation const &lhs, evaluation const &rhs)
Less-than-or-equal operator.
evaluation op_mod(evaluation const &lhs, evaluation const &rhs)
Modulus operator.
void cut(size_t start, size_t end)
Logically delete part of the evaluated text.
evaluation op_ge(evaluation const &lhs, evaluation const &rhs)
Greater-than-or-equal operator.
std::vector< evaluation > _ternary_cond_stack
Stack of ternary conditional results;.
evaluation(expression_parser::*)(evaluation const &, evaluation const &) infix_operation
Type of an infix operation.
evaluation result() const
Get the result of parsing the expression.
bool is_simplified() const
Say whether the expression has been simplified.
expression_parser(chewer< sequence_type > &chew, reference const *ref=nullptr)
Construct given a chewer<sequence_type>
evaluation op_eq(evaluation const &lhs, evaluation const &rhs)
Equality operator.
precedence
Codes for operator precedences.
evaluation op_comma(evaluation const &lhs, evaluation const &rhs)
Comma operator.
evaluation infix_op(chewer< sequence_type > &chew, size_t end)
Evaluator for infix operations.
evaluation op_or(evaluation const &lhs, evaluation const &rhs)
Inclusive-or operator.
evaluation op_mult(evaluation const &lhs, evaluation const &rhs)
Multiplication operator.
A logically deleted parenthesis.
evaluation _eval
The evaluation that results from parsing the expression.
void restore_paren()
Restore all logically deleted parentheses.
evaluation op_divide(evaluation const &lhs, evaluation const &rhs)
Division operator.
evaluation op_ternary_either_or(evaluation const &lhs, evaluation const &rhs)
The ':' "operator". Pops the evaluation of the preceding `cond ?' from the stack. If cond is true, returns lhs; if cond is false returns rhs, else returns evaluation()
reference const * _ref
A pointer to the reference if any, that calls for expression parsing.
evaluation op_and(evaluation const &lhs, evaluation const &rhs)
And operator.
evaluation op_bit_or(evaluation const &lhs, evaluation const &rhs)
Bitwise OR operator.
`template struct chewer<CharSeq> is a cursor-like type that is associated with a character-sequence t...
Definition: chew.h:248
std::enable_if<(Precedence==0), evaluation >::type next_evaluator(chewer< sequence_type > &chew, size_t end)
Select the member function to recursively evaluate expressions in which the major operator has a give...
evaluation op_gt(evaluation const &lhs, evaluation const &rhs)
Greater-than operator.
void restore_paren(size_t loff, size_t roff)
Restore a prematurely deleted pair of parentheses.
void parse(chewer< sequence_type > &chew)
Evaluate text from a chewer<sequence_type>
deletion_code
Codes for logical deletion status.
evaluation op_bit_xor(evaluation const &lhs, evaluation const &rhs)
Bitwise XOR operator.
evaluation unary_op(chewer< sequence_type > &chew, size_t end)
Evaluator for innermost subexpressions.
sequence_type & _seq
A reference to the character sequence being parsed.
evaluation op_ternary_if(evaluation const &lhs, evaluation const &rhs)
The '?' "operator". Stacks its left operand; returns its right.
A logically deleted non-parenthesis.
struct evaluation represents the result of evaluating a putative expression.
Definition: evaluation.h:48
size_t _start
Text offset at which evaluation starts.
std::pair< expression_parser::infix_operation, bool > seek_rightmost_infix(chewer< sequence_type > &chew, size_t end, size_t &op_start, size_t &op_end)
Search for the rightmost binary operator at a given level of precedence within delimited text...