2016-04-24 16 views
5

golang's yacc toolを使用してパーサーを作成しようとしています。私はnexを見つけて、パーサに与えるためのレクサーの作成を簡単にしました。私の問題は、生成されたパーサには解析結果にアクセスするためのメソッドやフィールドがないことです。解析結果をグローバル変数に格納するだけでも問題はないようです。現在、私は私のparser.yファイルの先頭に最初の試みとして、以下を追加しましたgolang yacc生成パーサーの結果にアクセス

type ResultParser interface { 
    yyParser // Generated parser interface 
    Result() s.Expr // s.Expr is an interface for the parsed result 
} 

func (p *yyParserImpl) Result() s.Expr { 
    return p.stack[1].expr 
} 

func NewResultParser() ResultParser { 
    return &yyParserImpl{} 
} 

は、パーサーから結果になってのお奨め/より良い方法はありますか?

+0

あなたは、解析結果とはどういう意味ですか? – andlabs

+0

入力を解析すると、私はツリー構造を構築します。これは '$$。expr'に格納されます。私はその木の根を手に入れたい。上記の「Result」関数は正しい結果にアクセスするようですが、ちょっとハッキリです。私は 'p.stack [1]'がルート/解析結果が常に格納される場所であることを100%確信していません... –

+1

yaccの文書化されていないデータ構造にうんざりしないでください。私はそれが "グローバル変数"か "yyLexerインターフェイスの基になる型のフィールド"のどちらかだと思います。私は後者を使用します – andlabs

答えて

5

ありません(これは発電機の乱用のビット...のように感じているので)、stack[1]へのアクセスは確実に機能しません。スタックが初期サイズの16を超えて成長しなければならないとすぐには結果は含まれません。 (#16163を参照してください。)

if文をyystackラベルは、新しいスタックを作成し、完全にyyParserImplに保存された1について忘れ後。


私は以下のことをしました。

レクサー型にresultフィールドを追加します。

type ShellLexer struct { 
    /* … */ 
    result *ShellProgram 
} 

は非常に先頭に次のルールで文法を拡張:

start : program { 
    shyylex.(*ShellLexer).result = $$ 
} 

(これはParseメソッドのパラメータ名に依存します(これはカスタムプレフィックスを持つことができますが、私はそうだと思います)

1

代替ソリューション:sedを使用して生成されたパーサー。次に、文法アクションで値を割り当てます。

go tool yacc -o parser.go -p Filter parser.y 
sed -i '/type FilterParserImpl struct/a tree *treeNode' parser.go 

生成されたパーザ:

type FilterParserImpl struct { 
tree *treeNode 
    lval FilterSymType 
    stack [FilterInitialStackSize]FilterSymType 
    char int 
} 

文法アクション:

filter { Filterrcvr.tree = $1 } 
関連する問題