私の環境ではboost :: spiritを使用することはできません。しかし、私はSTLを使用して、できるだけ自分自身のエクスプレッション・エバリュエーターを構築したいと思っています。 boost :: spiritのような代替手段はありますか?数式表現エバリュエーターの作成
10
A
答えて
0
YACCの++は、C++アプリケーション用のパーサジェネレータのための非常に良いツールです。 ANTLRはまた、C/C++での使用方法に関する良い文書を持っていません。
1
次のコードは、ユニットテストとIはACCU 200X(8または9)で約90分のセッションに書いた完全なパーサーを含みます。あなたがもっと必要な場合は、それを伸ばすだけでも簡単です。 Parse::value_type
を定義するか、それを別のヘッダファイルに抽出してテンプレートクラスにすることで、2倍にすることができます。
それとも、テストケースを取ると、自分を試すことができます。 (それはhttp://cute-test.comからCUTE使用しています)
#include "cute.h"
#include "ide_listener.h"
#include "cute_runner.h"
#include <cctype>
#include <map>
namespace {
class Parser {
typedef int value_type;
typedef std::vector<value_type> valuestack;
typedef std::vector<char> opstack;
typedef std::map<std::string,value_type> memory;
public:
memory variables;
private:
void evaluateSingleOperator(char op,value_type &result,value_type operand) {
switch(op) {
case '+': result += operand; break;
case '-': result -= operand; break;
case '*': result *= operand; break;
case '/': result /= operand; break;
default: throw("invalid operand");
}
}
void evaluateStacks(valuestack &values, opstack &ops) {
while(ops.size() && values.size()>1) {
char op = ops.back(); ops.pop_back();
value_type operand = values.back(); values.pop_back();
evaluateSingleOperator(op,values.back(),operand);
}
}
bool higherPrecedenceOrLeftAssociative(char last, char current) {
return (last == current)||(last == '*' || last == '/') ;
}
bool shouldEvaluate(char op,opstack const &ops) {
return ops.size() > 0 && higherPrecedenceOrLeftAssociative(ops.back(),op);
}
std::string parseVariableName(std::istream &is) {
std::string variable;
char nextchar=0;
while ((is >> nextchar) && isalpha(nextchar)) {
variable += nextchar;
}
if (variable.size() == 0) throw std::string("internal parse error");
is.unget();
return variable;
}
int peekWithSkipWhiteSpace(std::istream &is) {
int nextchar = EOF;
while(isspace(nextchar = is.peek())) is.get();
return nextchar;
}
value_type getOperand(std::istream &is) {
int nextchar = peekWithSkipWhiteSpace(is);
if (nextchar == EOF) throw std::string("syntax error operand expected");
if (isdigit(nextchar)){
value_type operand=0;
if (!(is >> operand)) throw std::string("syntax error getting number") ;
return operand;
} else if ('(' == nextchar) {
is.get();
return parse(is);
} else if (isalpha(nextchar)) {
std::string variable= parseVariableName(is);
if(parseAssignmentOperator(is)) {
variables[variable] = parse(is);
} else {
if (!variables.count(variable)) throw std::string("undefined variable: ")+variable;
}
return variables[variable];
}
throw std::string("syntax error");
}
bool parseAssignmentOperator(std::istream &is) {
int nextchar = peekWithSkipWhiteSpace(is);
if ('=' != nextchar) {
return false;
}
is.get();
return true;
}
public:
value_type parse(std::istream &is) {
is >> std::skipws;
valuestack values;
opstack ops;
values.push_back(getOperand(is));
char op=')';
while((is >>op) && op != ')') {
if (shouldEvaluate(op, ops)) {
evaluateStacks(values, ops);
}
values.push_back(getOperand(is));
ops.push_back(op);
}
evaluateStacks(values,ops);
return values.back();
}
value_type eval(std::string s) {
std::istringstream is(s);
return parse(is);
}
};
int eval(std::string s) {
return Parser().eval(s);
}
void shouldThrowEmptyExpression() {
eval("");
}
void shouldThrowSyntaxError() {
eval("()");
}
void testSimpleNumber() {
ASSERT_EQUAL(5,eval("5"));
}
void testSimpleAdd() {
ASSERT_EQUAL(10,eval("5 +5"));
}
void testMultiAdd() {
ASSERT_EQUAL(10,eval("1 + 2 + 3+4"));
}
void testSimpleSubtract() {
ASSERT_EQUAL(5,eval("6-1"));
}
void testTenPlus12Minus100() {
ASSERT_EQUAL(-78,eval("10+12-100"));
}
void testMultiply() {
ASSERT_EQUAL(50,eval("10*5"));
}
void testDivision() {
ASSERT_EQUAL(7,eval("21/3"));
}
void testAddThenMultiply() {
ASSERT_EQUAL(21,eval("1+4 *5"));
}
void testAddThenMultiplyAdd() {
ASSERT_EQUAL(16,eval("1+4*5 -5"));
}
void testAddSubSub() {
ASSERT_EQUAL(-4,eval("1+2-3-4"));
}
void testSimpleParenthesis() {
ASSERT_EQUAL(1,eval("(1)"));
}
void testSimpleOperandParenthesis() {
ASSERT_EQUAL(2,eval("1+(1)"));
}
void testParenthesis() {
ASSERT_EQUAL(5,eval("2*(1+4)-5"));
}
void testNestedParenthesis() {
ASSERT_EQUAL(16,eval("2*(1+(4*3)-5)"));
}
void testDeeplyNestedParenthesis() {
ASSERT_EQUAL(8,eval("((2*((1+(4*3)-5)))/2)"));
}
void testSimpleAssignment() {
Parser p;
ASSERT_EQUAL(1, p.eval("a=1*(2-1)"));
ASSERT_EQUAL(8, p.eval("a+7"));
ASSERT_EQUAL(1, p.eval("2-a"));
}
void testLongerVariables() {
Parser p;
ASSERT_EQUAL(1, p.eval("aLongVariableName=1*(2-1)"));
ASSERT_EQUAL(42, p.eval("AnotherVariable=7*(4+2)"));
ASSERT_EQUAL(1, p.eval("2-(aLongVariableName*AnotherVariable)/42"));
}
void shouldThrowUndefined() {
eval("2 * undefinedVariable");
}
void runSuite(){
cute::suite s;
//TODO add your test here
s.push_back(CUTE_EXPECT(CUTE(shouldThrowEmptyExpression),std::string));
s.push_back(CUTE_EXPECT(CUTE(shouldThrowSyntaxError),std::string));
s.push_back(CUTE(testSimpleNumber));
s.push_back(CUTE(testSimpleAdd));
s.push_back(CUTE(testMultiAdd));
s.push_back(CUTE(testSimpleSubtract));
s.push_back(CUTE(testTenPlus12Minus100));
s.push_back(CUTE(testMultiply));
s.push_back(CUTE(testDivision));
s.push_back(CUTE(testAddThenMultiply));
s.push_back(CUTE(testAddSubSub));
s.push_back(CUTE(testAddThenMultiplyAdd));
s.push_back(CUTE(testSimpleParenthesis));
s.push_back(CUTE(testSimpleOperandParenthesis));
s.push_back(CUTE(testParenthesis));
s.push_back(CUTE(testNestedParenthesis));
s.push_back(CUTE(testDeeplyNestedParenthesis));
s.push_back(CUTE(testSimpleAssignment));
s.push_back(CUTE(testLongerVariables));
s.push_back(CUTE_EXPECT(CUTE(shouldThrowUndefined),std::string));
cute::ide_listener lis;
cute::makeRunner(lis)(s, "The Suite");
}
}
int main(){
runSuite();
}
関連する問題
- 1. Choco Solver数式表現の生成
- 2. 数学正規表現式
- 3. 多数の数式表現ですか?
- 4. 正規表現を作成して式の数値をテストする方法は?
- 5. 正規表現の作成
- 6. 正規表現の作成?
- 7. Javaでカスタム表現エバリュエーターを実装する正しい方法は?
- 8. 表現形式
- 9. SparseTensorsのテンソルをエバリュエーターにフィード
- 10. 正規表現式
- 11. 正規表現式
- 12. この形式の正規表現を作成する方法B001169875?
- 13. レポートデザイナーの列の表現式
- 14. python3の正規表現のモジュラー関数を作成する
- 15. 正規表現のサブ式
- 16. ZendのFastRouteグループ表現式
- 17. 正規表現のパターン式
- 18. PHPの正規表現式
- 19. JSON形式のOWLClass表現
- 20. Python比較エバリュエーター置換
- 21. 正規表現数値の書式なしconsercutive - - 数
- 22. より速い正規表現clr関数を作成する
- 23. 式ツリーは - 代替表現
- 24. 正規表現式支援
- 25. 正規表現式文パターン
- 26. Asp.net正規表現バリデーターバリデーション式
- 27. 正規表現を作成する
- 28. 正規表現パターンを作成する
- 29. 正規表現を作成する
- 30. 大きな数字を扱うC#数式表現パーサー
独自のロール? CoCo/R?フレックス/バイソンですか? lex/yacc? ANTLR?もちろん、評価者は含まれていませんが、堅実な文法を与えれば些細なはずです – sehe
@ありがとうございます。私が言及したパーサジェネレータのいくつかを知っていると思うが、私はそれらがcまたはcのようなコードを生成していると思った。少なくともSTLを使用しているものはありますか? –
[Boost.Proto](http://www.boost.org/libs/proto/)はBoostのエクスプレッションエバリュエーターライブラリです。 Boost.Spiritは_parsing_ライブラリです(Boost.Protoの上に構築されています)。 – ildjarn