忍者ブログ
ゲーム関連の話題に絞っていましたが、全然書かないのでいろいろ解禁してみたり。
[11]  [10]  [9]  [8]  [7]  [6]  [5]  [4]  [3]  [2]  [1
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

とりあえずラストです。
これが私の限界……これ以上大きくなるとどう考えてもどこかで破綻しそうなのです……
って、絶対に使い方が間違っているのが原因なのですけどねっ♪ orz

今回も使い方的には変わっていないので全ソースをそのまま……
 

#pragma warning(disable:4512) //代入演算子を生成できません。
#pragma warning(disable:4100) //引数は関数の本体部で 1 度も参照されません。

#include <iostream>
#include <map>
#include <string>
#include <stack>

#include <boost/bind.hpp>
#include <boost/spirit/home/qi.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>


class VariableManager{
public:
 void Set(std::string name, int value){
  container[name] = value;
 }

 int Get(std::string name){
  return container[name];
 }

private:
 typedef std::map<std::string, int> Container;
 Container container;
};

template<typename String>
struct CalcPlusAlpha : boost::spirit::qi::grammar<typename String::const_iterator, boost::spirit::ascii::space_type>{
public:
 typedef typename String::const_iterator Iterator;

 int GetResult() const{
  int i = stack.top();
  Reset();
  return i;
 }

 void Reset() const{
  std::stack<int> empty;
  std::swap(empty, stack);
 }

 CalcPlusAlpha() : CalcPlusAlpha::base_type(line){
  using namespace boost;

  using namespace boost::spirit;
  namespace sp_arg = boost::spirit::arg_names;

  // 構文定義
  line  = expression | teigi | dainu;

  group  = '(' >> expression >> ')';
  factor  = int_[bind(&CalcPlusAlpha::PUSH, this, _1)] | group;
  term  = factor >> *( ('*' >> factor)[bind(&CalcPlusAlpha::MUL, this)] | ('/' >> factor)[bind(&CalcPlusAlpha::DIV, this)] );
  expression = term >> *( ('+' >> term)[bind(&CalcPlusAlpha::ADD, this)] | ('-' >> term)[bind(&CalcPlusAlpha::SUB, this)] );

  teigi  = lexeme["int" >> +ascii::space >> variable[bind(&CalcPlusAlpha::VAL_ADD, this, _1)]];
  variable = lexeme[ascii::alpha[sp_arg::_val += sp_arg::_1] >> *ascii::alnum[sp_arg::_val += sp_arg::_1]];

  dainu  = variable[bind(&CalcPlusAlpha::VAL_DAINU_BEGIN, this, _1)] >> "=" >> expression[bind(&CalcPlusAlpha::VAL_DAINU, this)];
 };
 
 boost::spirit::qi::rule<Iterator, boost::spirit::ascii::space_type> line;

 boost::spirit::qi::rule<Iterator, boost::spirit::ascii::space_type> expression;
 boost::spirit::qi::rule<Iterator, boost::spirit::ascii::space_type> term;
 boost::spirit::qi::rule<Iterator, boost::spirit::ascii::space_type> factor;
 boost::spirit::qi::rule<Iterator, boost::spirit::ascii::space_type> group;

 boost::spirit::qi::rule<Iterator, boost::spirit::ascii::space_type> teigi;
 boost::spirit::qi::rule<Iterator, String(), boost::spirit::ascii::space_type> variable;

 boost::spirit::qi::rule<Iterator, boost::spirit::ascii::space_type> dainu;

public:
 std::stack<int> stack;
 VariableManager vm;

 String temp;

 void VAL_DAINU_BEGIN(String name){
  temp.swap(name);
 }
 void VAL_DAINU(){
  VAL_IN(temp, GetResult());
 }

 void VAL_ADD(String name){
  vm.Set(name, 0);
 }

 void VAL_IN(String name, int value){
  vm.Set(name, value);
 }

 void PUSH(int i){
  stack.push(i);
 }

 void ADD(){
  int a = stack.top();
  stack.pop();
  int b = stack.top();
  stack.pop();

  stack.push(b + a); 
 }

 void SUB(){
  int a = stack.top();
  stack.pop();
  int b = stack.top();
  stack.pop();

  stack.push(b - a);
 }

 void MUL(){
  int a = stack.top();
  stack.pop();
  int b = stack.top();
  stack.pop();

  stack.push(b * a);
 }
 
 void DIV(){
  int a = stack.top();
  stack.pop();
  int b = stack.top();
  stack.pop();

  stack.push(b / a);
 }
};


int main(void)
{
 CalcPlusAlpha<std::string> calc;

 std::string str;
 while (getline(std::cin, str))
 {
  if (str.empty() || str[0] == 'q' || str[0] == 'Q')
   break;

  std::string::const_iterator it = str.begin();
  std::string::const_iterator end = str.end();

  bool result = phrase_parse(it, end, calc, boost::spirit::ascii::space);

  if (result && it == end)
  {
   std::cout << "-------------------------\n";
   std::cout << "Parsing succeeded\n";
   std::cout << str << " Parses OK: " << std::endl;
  }
  else if(result)
  {
   std::cout << "-------------------------\n";
   std::cout << "Parsing succeeded\n";
   std::cout << std::string(str.begin(), it) << " Parses OK: " << std::endl;
   std::cout << std::string(it, end) << " amari" << std::endl;
  }
  else
  {
   std::cout << "-------------------------\n";
   std::cout << "Parsing failed\n";
   std::cout << "-------------------------\n";
   calc.Reset();
  }
 }

 return 0;
}

えーっと、変数管理クラスがずさんとか、構文がいい加減とか、変数定義して代入できるけど変数を式に組み込めないとか、変数の確認が出来ないとか言う苦情は聞きませんっ。
変数の中身が知りたい人はデバッガを使えばいいのですっ。


閑話休題。
もうちょっとがんばれば変数の取り出しぐらいは出来そうな気もするのですけど……
後これに(ノベルゲームの構文解析に使う予定なので)大小比較、組み込み関数呼び出し、普通の文字列はそのまま表示、ifとwhileの実装……と考えると破綻しそうで怖いのです……

このままspiritでがんばるか、とりあえずしょぼくなること請け合いでもフルスクラッチするかはもうちょっと考えるのですけど……どうしましょう……

//2009-10-25追記
コードの修正(mutableとconstの勘違い)

PR
この記事にコメントする
お名前
タイトル
文字色
メールアドレス
URL
コメント
パスワード   Vodafone絵文字 i-mode絵文字 Ezweb絵文字
この記事へのトラックバック
この記事にトラックバックする:
Twitter
Twitter Update
ブログ内検索
カレンダー
05 2025/06 07
S M T W T F S
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
最新コメント
最新トラックバック
プロフィール
HN:
100poisha
性別:
非公開
アクセス解析
Copyright © 100poishaのブログ All Rights Reserved.
Designed by north sound
Powered by Ninja Blog

忍者ブログ [PR]