houken sample.peg
sample.tab.h |
自動生成されたパーサのヘッダファイル |
sample.tab.cpp |
自動生成されたパーサのソースファイル |
sample.tab.tmpl |
ユーザが実装すべきアクション関数のテンプレート。これをコピーして中身を実装していくと良い。 |
sample.tab.up |
A
<% e
ルールにより自動生成を停止された、ユーザが実装すべきパーサ関数のテンプレート。これをコピーして中身を実装し
ていくと良い。 |
sample.tab.ua |
宝剣ソースコード中で使用するアクション関数の宣言をまとめたヘッダファイル。これを userActionFuncDef.h にコピーすると良い。 |
sysDep.h
と sysDep.cpp
を用意する。Parser
クラスの子クラスであり、メンバ関数
SyntaxTree* parse(void)
を持つ。Number
であれば、クラス名は P_Number
というように、頭に P_
がついたものとなる。p_
がついたものとなる。P_Number
クラスなら p_Number
という名前のインスタンスとなる。Number
の解析をしたいのであれば、SyntaxTree* st = p_Number->parse();
$action
にて指定したアクション関数をユーザは実装する。$action
action(Application*)
Number <- [0-9]+
virtual void SyntaxTree::action(Application*)
Parser
クラスを継承したP_Number
ク
ラスと、SyntaxTree
クラスを継承したST_Number
ク
ラスが定義され、メンバ関数void
ST_Number::action(Application*)
void P_Number::actionAtParse(SyntaxTree*)
actionAtParse()
は、パースが成功した時点で呼ばれる。$ctype
を実現するために使用している。#include
のような動作をさせるために使用できるだろう。 void ST_Number::action(Application* ap) {// 処理して結果を ap に入れる } SyntaxTree* st = p_Number->parse(); // p_Number からは ST_Number オブジェクトが生成される if (st->isValidTree()) { Application app; st->action(&app); // ST_Number::action() が呼び出される // 結果が app に入っている } |
A <- B $3 C
というルールがあり、これを元にパースし、B が成功して $3 を通過した後 C が失敗するとエラーとなり、A の
errorMessage関数が呼ばれる。
引数として、3 と、パースに失敗した位置(この場合は C の位置)が渡される。
A <% e
SyntaxTree* P_A::uParse(void)
actionAtParse()
関数は宣言され
ない。uParse()
関数を実装する。
SyntaxTree
オブジェクトに格納される。SyntaxTree
は、Parser
オブジェクトへのポイン
タSyntaxTree
の配列オブジェク
トへのポインタSubstr
構造体で入力開始位置と
終了位置)Number <- [0-9]+
[0-9]
となる。123ab
をNumber
でパースすると、消
費した入力は 123
となる。SyntaxTree
は3つとなり、最初の子は 1 を消費し、Number <- %[0-9]+
%
の機能により子が生成したSyntaxTree
は
全部捨てられ、0個になる。SyntaxTree
は3つの子"+"
が infixl
、 "**"
が infixr
の場合、入力とそのパース結果のSyntaxTreeをおおまかに示すと以下の
ようになる。1+2+3 → (("1","+","2"),"+","3")
1**2**3 → ("1","**",("2","**","3"))
これを元に演算を実行する場合、各子のアクション関数を呼んで、その結果を使って自分の演算をするようなアクション関数をプロ
グラムすれば良い。真となる判定関数 | 意味 | 定義済み値 | |
---|---|---|---|
正常値 | isValidTree() |
成功したパース結果を保持する。 | |
結果を削除 | == _NO_SYNTAX_TREE |
成功だが、値を捨てた状態。 | _NO_SYNTAX_TREE |
パース失敗 | isFail(), isFailNotError() |
パースに失敗した状態。 | _PARSE_FAILED |
エラーカット | isErrorCut() |
ErrorCutを示す。この後にパース失敗するとそれはエラーとなるように内部的に処理される。ErrorCut番号 を保持する。 | |
エラー | isFail(), isError() |
ErrorCut機能によりパース失敗がエラーに変換されたもの。ErrorCut番号を保持する。内部的に ErrorMessage()を呼び出し、その後は致命的エラー状態になる。 | |
致命的エラー | isFail(), isError(), isFatalError() |
パースもエラー処理もこれ以上行わないで終了させる状態。 | _FATAL_PARSER_ERROR |
'token'
)を使う場合は、ユーザーが NotTokenPred
ルールを定義しなければならない。
入力を消費しないようにする事。 !
か &
を使えば入力を消費しない。NotTokenPred <- !([a-z]/[A-Z]/[0-9]/"_")
InputBuffer
を生成し、Houken::gpInp
に代入する。Parser::initialize()
を呼ぶparse()
を呼ぶ_PARSE_FAILED
ならパース失敗_NO_SYNTAX_TREE
なら成功だが結果の情報は無し_FATAL_PARSER_ERROR
ならこれ以上パース出来ない致命的エラー状態isValidTree()
がtrue
を
返せば、有効なSyntaxTree
オブジェクトSyntaxTree
オ
ブジェクトのアクション関数を呼ぶ。SyntaxTree
やユーザーが使用したオブジェクトは delete
する。Parser::finalize() と SyntaxTree::finalize()
を呼ぶ。これで、生成された Parser
と SyntaxTree
は全て delete
される。ユーザーは自分で new
したものであっても Parser
を自分で delete
してはいけない。