2

ターゲット言語C#でANTLRを使用して解析ツリー(ASTではない)を作成したいと思います。これはささいなことではないようです、多分私はすべての間違った場所を探しています。

これまで、次のように、生成されたパーサーにパーシャルを実装しようとしました。

public partial class TestParser
{

   ParseTree pt = new ParseTree("root", null);

   partial void EnterRule(string ruleName, int ruleIndex)
   {
     ParseTree child = new ParseTree(ruleName, pt);
     pt.Children.Add(child);
     this.pt = child;
   }

   partial void LeaveRule(string ruleName, int ruleIndex)
   {
     this.pt = pt.Parent;
   }

}

ParseTreeあると

public class ParseTree
{
    private List<ParseTree> children = new List<ParseTree>();

    public ParseTree(string name, ParseTree parent)
    {
        this.Parent = parent;
        this.Rule = name;
    }

    public ParseTree Parent { get; private set; }
    public string Rule { get; private set; }
    public List<ParseTree> Children { get { return children; } }

    public Boolean IsTerminal
    {
        get
        {
            return (children.Count == 0);
        }
    }

}

これは機能しますが、私の目標を達成していません。このツリーから一致するトークン/テキストを取得できません。それとは別に、追加の欠点があります。複数の文法に対してこれを実行する場合、部分クラスはTestParserの部分であり、フードチェーンの上位にはないため、どこにでもコピーアンドペーストする必要があります。

http://www.antlr.org/wiki/pages/viewpage.action?pageId=1760を見ましたが、生成されたパーサーには、をとるコンストラクターがありませんParseTreeBuilder

これからどこ行く?

4

1 に答える 1

2

私は自分の問題に対して多かれ少なかれ合理的な解決策を見つけました。これには大きな欠点があります。トークンのみで構成されるプロダクションルールのテキストのみを処理します。これは私にとっては十分ですが、あなたにとってはそうではないかもしれません。適切な実装にはトークンノードも含まれている必要があります。これにより、適切にウォークできるようになります。

アダプタ:

    public class ParseAdaptor : CommonTreeAdaptor
    {
        private C<ParseTree> container;

        public ParseAdaptor(C<ParseTree> container)
            : base()
        {
            this.container = container;
        }

        public override void AddChild(object t, object child)
        {
            base.AddChild(t, child);
            this.container.Value.Text += base.GetTree(child).Text;
        }


    }

ParseTreeの実装:

public class ParseTree
{
    private string ownText;
    private List<ParseTree> children = new List<ParseTree>();

    public ParseTree(string name, ParseTree parent)
    {
        this.Parent = parent;
        this.Rule = name;
    }

    public String Text
    {
        get
        {
            if (this.IsTerminal) return this.ownText;
            else
            {
                StringBuilder builder = new StringBuilder();
                foreach (ParseTree child in children)
                {
                    builder.Append(child.Text);
                }
                return builder.ToString();
            }
        }
        set
        {
            this.ownText = value;
        }
    }

    public ParseTree Parent { get; private set; }
    public string Rule { get; private set; }
    public List<ParseTree> Children { get { return children; } }

    public Boolean IsTerminal
    {
        get
        {
            return (children.Count == 0);
        }
    }

}
//Isn't this the silliest little thing you've ever seen?
//Where is a pointer when you need one?
public class C<T>
{
    public T Value { get; set; }
}

そしてそれはパーシャルと一緒に接着されます:

    public partial class TestParser
    {

        C<ParseTree> parseTreeContainer = new C<ParseTree>() { Value = new ParseTree("root", null) };

        public ParseTree Tree
        {
            get
            {
                return parseTreeContainer.Value;
            }
            set
            {
                parseTreeContainer.Value = value;
            }
        }

        partial void CreateTreeAdaptor(ref ITreeAdaptor adaptor)
        {
            adaptor = new ParseAdaptor(this.parseTreeContainer);
        }

        partial void EnterRule(string ruleName, int ruleIndex)
        {
            ParseTree child = new ParseTree(ruleName, Tree);
            ParseTree parent = Tree;
            parent.Children.Add(child);
            Tree = child;
        }

        partial void LeaveRule(string ruleName, int ruleIndex)
        {
            Tree = Tree.Parent;
        }

    }
于 2012-12-10T15:56:36.327 に答える