1

a=b & s<9 または単純に a=b などのブール式を比較演算子のみ (|、&、! などの論理演算子なし) で評価したいと考えています。次の AST を使用できます。

            =
           / \
          /   \
          a    b 

また

               &
              / \  
             /   \
            =     <
           / \    /\
          /   \  /  \
          a    b s   9   

葉ノードは値です。Leave ノードの親は常に =、!=、<、>、>=、<= などの比較演算子です。比較ノードの親は、論理演算子 |、&、および ! です。親ノードから値ノード (葉) にアクセスし、これらの値を別の関数 (後で実装されます) に渡したいと思います。解析ステップは問題ありません。

親ノードから値ノード (葉) にアクセスする方法。私は次の例を使用しています: スピリットでブール式を計算する方法

c++ のブール式 (文法) パーサーこれ は、次のリンクから取得した評価コードです。

    struct eval : boost::static_visitor<bool>
{
    eval() {}

    ///
    bool operator()(const var& v) const
    {
        std::cout<<"feuille:\n"<<v<<std::endl;
        true を返します。
    }

    bool operator()(const binop<op_and>& b) const
    {
        再帰 (b.oper1) && 再帰 (b.oper2);
    }
    bool operator()(const binop<op_or>& b) const
    {
        再帰 (b.oper1) || 再帰 (b.oper2);
    }
    bool operator()(const unop<op_not>& u) const
    {
        return !recurse(u.oper1);
    }

    //------------他の演算子の追加--------------------------------
    bool operator()(const binop<op_equal>& u) const
    {
        // 後で実装されます
        true を返します。
    }

    bool operator()(const binop<op_not_equal>& u) const
    {
       // 後で実装されます
        true を返します。
    }

    bool operator()(const binop<op_less>& u) const
    {
        // 後で実装されます
        true を返します。
    }

    bool operator()(const binop<op_less_equal>& u) const
    {
        // 後で実装されます
        true を返します。
    }

    bool operator()(const binop<op_greater>& u) const
    {
        // 後で実装されます
        true を返します。
    }
    bool operator()(const binop<op_greater_equal>& u) const
    {
        // 後で実装されます
        true を返します。
    }


ありがとうございました。どんな提案でも大歓迎です。

4

1 に答える 1

1

既存の演算子の他の評価オーバーロードを見たことがありますか? オペランドの値を取得する方法に気付きましたか(実際にはサブ式である可能性があります)。

バイナリまたは例を挙げましょう:

bool operator()(const binop<op_or>& b) const
{
    return recurse(b.oper1) || recurse(b.oper2);
}

ご覧のとおり||、両方のオペランドの値に適用されます。その値は AST [1]にはありません。したがって、各オペランドを式として扱い、そのevalメソッドを再帰的に呼び出すだけです。

式の型はバリアントであるため、呼び出しevalは実際にはビジターをバリアントに適用しています。これを行う便利なラッパーを既に作成しているので、次のことは簡単recurseです。

private:
template<typename T>
    bool recurse(T const& v) const 
    { return boost::apply_visitor(*this, v); }

したがって、文法の残りの部分はわかりませんが、既存の文法と同じように拡張すると仮定します。

bool operator()(const binop<op_equal>& u) const {
    return recurse(b.oper1) == recurse(b.oper2);
}

ほぼ正しいでしょう。巧妙なマクロを使用すると、非常に迅速に実行できることに注意してください。

struct eval : boost::static_visitor<value> {

    // terminal
    value operator()(const var& v) const {
        std::cout<<"feuille:\n"<<v<<std::endl;
        return true; // TODO get value from var
    }

    // unary operator
    value operator()(const unop<op_not>& u) const { return !recurse(u.oper1); }

    /*
     * binary operators
     */
#define EXPR_DEF_BINOP(tag, op) \
    value operator()(const binop<tag>& u) const { \
        return recurse(b.oper1) op recurse(b.oper2); \
    }

    EXPR_DEF_BINOP(op_and,           &&)
    EXPR_DEF_BINOP(op_equal,         ==)
    EXPR_DEF_BINOP(op_greater,       >)
    EXPR_DEF_BINOP(op_greater_equal, >=)
    EXPR_DEF_BINOP(op_less,          <)
    EXPR_DEF_BINOP(op_less_equal,    <=)
    EXPR_DEF_BINOP(op_not_equal,     !=)
    EXPR_DEF_BINOP(op_or,            ||)

#undef EXPR_DEF_BINOP

  private:
    template<typename T>
        value recurse(T const& v) const 
        { return boost::apply_visitor(*this, v); }
};

その他の注意事項:

  • リーフノード評価関数にTODOを追加しました
  • タイプをvalue(from bool) に変更しました。これは、文法が非ブール式をサポートしているためです。それ以外の場合は、演算子<=>=意味がありません。[2]、したがって、さまざまなタイプの値を持つことになります (あまりにも):

    using value = variant<bool, int32_t>;
    

    残りはあなたに任せます


[1] AST = 抽象構文ツリーを思い出してください。これは、ソースの 1:1 表現です。(「半分の例外」はリテラルですが、リテラルの値の使用方法を評価者に伝える必要があります。)

[2]間違いなく

  • a<b 暗示することができます!a && b
  • a>b 暗示することができます!b && a
  • a!=b暗示することができますa XOR b
  • a==b暗示することができます!(a XOR b)
于 2013-10-18T12:32:01.813 に答える