Overte C++ Documentation
AnimExpression.h
1 //
2 // AnimExpression.h
3 //
4 // Created by Anthony J. Thibault on 11/1/15.
5 // Copyright (c) 2015 High Fidelity, Inc. All rights reserved.
6 //
7 // Distributed under the Apache License, Version 2.0.
8 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
9 //
10 
11 #ifndef hifi_AnimExpression
12 #define hifi_AnimExpression
13 
14 #include <QString>
15 #include <glm/glm.hpp>
16 #include <glm/gtc/quaternion.hpp>
17 #include <stack>
18 #include <vector>
19 #include "AnimVariant.h"
20 
21 class AnimExpression {
22 public:
23  friend class AnimTests;
24  explicit AnimExpression(const QString& str);
25 protected:
26  struct Token {
27  enum Type {
28  End = 0,
29  Identifier,
30  Bool,
31  Int,
32  Float,
33  And,
34  Or,
35  GreaterThan,
36  GreaterThanEqual,
37  LessThan,
38  LessThanEqual,
39  Equal,
40  NotEqual,
41  LeftParen,
42  RightParen,
43  Not,
44  Minus,
45  Plus,
46  Multiply,
47  Divide,
48  Modulus,
49  Comma,
50  Error
51  };
52  explicit Token(Type type) : type {type} {}
53  explicit Token(const QStringRef& strRef) : type {Type::Identifier}, strVal {strRef.toString()} {}
54  explicit Token(int val) : type {Type::Int}, intVal {val} {}
55  explicit Token(bool val) : type {Type::Bool}, intVal {val} {}
56  explicit Token(float val) : type {Type::Float}, floatVal {val} {}
57  Type type {End};
58  QString strVal;
59  int intVal {0};
60  float floatVal {0.0f};
61  };
62 
63  struct OpCode {
64  enum Type {
65  Identifier,
66  Bool,
67  Int,
68  Float,
69  And,
70  Or,
71  GreaterThan,
72  GreaterThanEqual,
73  LessThan,
74  LessThanEqual,
75  Equal,
76  NotEqual,
77  Not,
78  Subtract,
79  Add,
80  Multiply,
81  Divide,
82  Modulus,
83  UnaryMinus
84  };
85  explicit OpCode(Type type) : type {type} {}
86  explicit OpCode(const QStringRef& strRef) : type {Type::Identifier}, strVal {strRef.toString()} {}
87  explicit OpCode(const QString& str) : type {Type::Identifier}, strVal {str} {}
88  explicit OpCode(int val) : type {Type::Int}, intVal {val} {}
89  explicit OpCode(bool val) : type {Type::Bool}, intVal {(int)val} {}
90  explicit OpCode(float val) : type {Type::Float}, floatVal {val} {}
91 
92  bool coerceBool(const AnimVariantMap& map) const {
93  if (type == Int || type == Bool) {
94  return intVal != 0;
95  } else if (type == Identifier) {
96  return map.lookup(strVal, false);
97  } else {
98  return true;
99  }
100  }
101 
102  Type type {Int};
103  QString strVal;
104  int intVal {0};
105  float floatVal {0.0f};
106  };
107 
108  void unconsumeToken(const Token& token);
109  Token consumeToken(const QString& str, QString::const_iterator& iter) const;
110  Token consumeIdentifier(const QString& str, QString::const_iterator& iter) const;
111  Token consumeNumber(const QString& str, QString::const_iterator& iter) const;
112  Token consumeAnd(const QString& str, QString::const_iterator& iter) const;
113  Token consumeOr(const QString& str, QString::const_iterator& iter) const;
114  Token consumeGreaterThan(const QString& str, QString::const_iterator& iter) const;
115  Token consumeLessThan(const QString& str, QString::const_iterator& iter) const;
116  Token consumeNot(const QString& str, QString::const_iterator& iter) const;
117 
118  bool parseExpr(const QString& str, QString::const_iterator& iter);
119  bool parseExprPrime(const QString& str, QString::const_iterator& iter);
120  bool parseTerm(const QString& str, QString::const_iterator& iter);
121  bool parseTermPrime(const QString& str, QString::const_iterator& iter);
122  bool parseUnary(const QString& str, QString::const_iterator& iter);
123  bool parseFactor(const QString& str, QString::const_iterator& iter);
124 
125  OpCode evaluate(const AnimVariantMap& map) const;
126  void evalAnd(const AnimVariantMap& map, std::stack<OpCode>& stack) const;
127  void evalOr(const AnimVariantMap& map, std::stack<OpCode>& stack) const;
128  void evalGreaterThan(const AnimVariantMap& map, std::stack<OpCode>& stack) const;
129  void evalGreaterThanEqual(const AnimVariantMap& map, std::stack<OpCode>& stack) const;
130  void evalLessThan(const AnimVariantMap& map, std::stack<OpCode>& stack) const;
131  void evalLessThanEqual(const AnimVariantMap& map, std::stack<OpCode>& stack) const;
132  void evalEqual(const AnimVariantMap& map, std::stack<OpCode>& stack) const;
133  void evalNotEqual(const AnimVariantMap& map, std::stack<OpCode>& stack) const;
134  void evalNot(const AnimVariantMap& map, std::stack<OpCode>& stack) const;
135  void evalSubtract(const AnimVariantMap& map, std::stack<OpCode>& stack) const;
136  void evalAdd(const AnimVariantMap& map, std::stack<OpCode>& stack) const;
137  void add(int lhs, const OpCode& rhs, std::stack<OpCode>& stack) const;
138  void add(float lhs, const OpCode& rhs, std::stack<OpCode>& stack) const;
139  void evalMultiply(const AnimVariantMap& map, std::stack<OpCode>& stack) const;
140  void mul(int lhs, const OpCode& rhs, std::stack<OpCode>& stack) const;
141  void mul(float lhs, const OpCode& rhs, std::stack<OpCode>& stack) const;
142  void evalDivide(const AnimVariantMap& map, std::stack<OpCode>& stack) const;
143  void evalModulus(const AnimVariantMap& map, std::stack<OpCode>& stack) const;
144  void evalUnaryMinus(const AnimVariantMap& map, std::stack<OpCode>& stack) const;
145 
146  OpCode coerseToValue(const AnimVariantMap& map, const OpCode& opCode) const;
147 
148  QString _expression;
149  mutable std::stack<Token> _tokenStack; // TODO: remove, only needed during parsing
150  std::vector<OpCode> _opCodes;
151 
152 #ifndef NDEBUG
153  void dumpOpCodes() const;
154 #endif
155 };
156 
157 #endif
158