Tclのトークン分割機能をC/C++から直接呼び出してみるテスト
Tcl を C/C++ で活用する・・・というと、Tcl_Eval で Tcl の各種コマンドを呼び出す方法をまず思いつきますが、
Tcl_Eval を使う以外にも、文字列処理や、ファイル処理、参照カウンタ式のオブジェクト管理等、
色々便利そうな API が結構揃っていて、純粋に C/C++ 用のライブラリとしても使えそうな感じです。
Tcl_Eval を使う以外にも、文字列処理や、ファイル処理、参照カウンタ式のオブジェクト管理等、
色々便利そうな API が結構揃っていて、純粋に C/C++ 用のライブラリとしても使えそうな感じです。
<実験コード>
void tokenize_test(){
const char *some_tcl_script[] = {
"hello {ABC DEF GHI} [hoge AA BB $CC] $def OKOK # comment start",
"hello {ABC DEF \nGHI} [hoge AA BB $CC] $def OKOK #comment start"
};
for (int j = 0; j < 2; ++j){
std::printf("[%d]\n", j+1);
Tcl_Parse parse;
::Tcl_ParseCommand(0, some_tcl_script[j], -1, 0, &parse);
std::printf("command:");
std::fwrite(parse.commandStart, parse.commandSize, 1, stdout);
std::printf("\n");
for (int i = 0; i < parse.numTokens; ++i){
Tcl_Token &tok = parse.tokenPtr[i];
std::printf("token[%d] (%d):", i + 1, tok.type);
std::fwrite(tok.start, tok.size, 1, stdout);
std::printf("\n");
}
std::printf("comment:%s\n", parse.commentStart);
::Tcl_FreeParse(&parse);
}
}
const char *some_tcl_script[] = {
"hello {ABC DEF GHI} [hoge AA BB $CC] $def OKOK # comment start",
"hello {ABC DEF \nGHI} [hoge AA BB $CC] $def OKOK #comment start"
};
for (int j = 0; j < 2; ++j){
std::printf("[%d]\n", j+1);
Tcl_Parse parse;
::Tcl_ParseCommand(0, some_tcl_script[j], -1, 0, &parse);
std::printf("command:");
std::fwrite(parse.commandStart, parse.commandSize, 1, stdout);
std::printf("\n");
for (int i = 0; i < parse.numTokens; ++i){
Tcl_Token &tok = parse.tokenPtr[i];
std::printf("token[%d] (%d):", i + 1, tok.type);
std::fwrite(tok.start, tok.size, 1, stdout);
std::printf("\n");
}
std::printf("comment:%s\n", parse.commentStart);
::Tcl_FreeParse(&parse);
}
}
<結果>
[1]
command:hello {ABC DEF GHI} [hoge AA BB $CC] $def OKOK # comment start
token[1] (2):hello
token[2] (4):hello
token[3] (2):{ABC DEF GHI}
token[4] (4):ABC DEF GHI
token[5] (1):[hoge AA BB $CC]
token[6] (16):[hoge AA BB $CC]
token[7] (1):$def
token[8] (32):$def
token[9] (4):def
token[10] (2):OKOK
token[11] (4):OKOK
token[12] (2):#
token[13] (4):#
token[14] (2):comment
token[15] (4):comment
token[16] (2):start
token[17] (4):start
comment:(null)
[2]
command:hello {ABC DEF
GHI} [hoge AA BB $CC] $def OKOK #comment start
token[1] (2):hello
token[2] (4):hello
token[3] (2):{ABC DEF
GHI}
token[4] (4):ABC DEF
GHI
token[5] (1):[hoge AA BB $CC]
token[6] (16):[hoge AA BB $CC]
token[7] (1):$def
token[8] (32):$def
token[9] (4):def
token[10] (2):OKOK
token[11] (4):OKOK
token[12] (2):#comment
token[13] (4):#comment
token[14] (2):start
token[15] (4):start
comment:(null)
()内の数字は トークンの type を表していて、tcl.h に次のように定義されています。command:hello {ABC DEF GHI} [hoge AA BB $CC] $def OKOK # comment start
token[1] (2):hello
token[2] (4):hello
token[3] (2):{ABC DEF GHI}
token[4] (4):ABC DEF GHI
token[5] (1):[hoge AA BB $CC]
token[6] (16):[hoge AA BB $CC]
token[7] (1):$def
token[8] (32):$def
token[9] (4):def
token[10] (2):OKOK
token[11] (4):OKOK
token[12] (2):#
token[13] (4):#
token[14] (2):comment
token[15] (4):comment
token[16] (2):start
token[17] (4):start
comment:(null)
[2]
command:hello {ABC DEF
GHI} [hoge AA BB $CC] $def OKOK #comment start
token[1] (2):hello
token[2] (4):hello
token[3] (2):{ABC DEF
GHI}
token[4] (4):ABC DEF
GHI
token[5] (1):[hoge AA BB $CC]
token[6] (16):[hoge AA BB $CC]
token[7] (1):$def
token[8] (32):$def
token[9] (4):def
token[10] (2):OKOK
token[11] (4):OKOK
token[12] (2):#comment
token[13] (4):#comment
token[14] (2):start
token[15] (4):start
comment:(null)
#define TCL_TOKEN_WORD 1
#define TCL_TOKEN_SIMPLE_WORD 2
#define TCL_TOKEN_TEXT 4
#define TCL_TOKEN_BS 8
#define TCL_TOKEN_COMMAND 16
#define TCL_TOKEN_VARIABLE 32
#define TCL_TOKEN_SUB_EXPR 64
#define TCL_TOKEN_OPERATOR 128
#define TCL_TOKEN_EXPAND_WORD 256
#define TCL_TOKEN_SIMPLE_WORD 2
#define TCL_TOKEN_TEXT 4
#define TCL_TOKEN_BS 8
#define TCL_TOKEN_COMMAND 16
#define TCL_TOKEN_VARIABLE 32
#define TCL_TOKEN_SUB_EXPR 64
#define TCL_TOKEN_OPERATOR 128
#define TCL_TOKEN_EXPAND_WORD 256
スペースやタブをトークン区切りにして、各トークンを純粋に取り出したい、といった場合は、
TCL_TOKEN_WORD、または TCL_TOKEN_SIMPLE_WORD のトークンだけを処理して、それ以外の
トークンは無視すれば使えそうな感じでしょうか。
TCL_TOKEN_WORD、または TCL_TOKEN_SIMPLE_WORD のトークンだけを処理して、それ以外の
トークンは無視すれば使えそうな感じでしょうか。
parse.commentStart がコメント開始箇所を見つけ出せてない理由が謎ですが・・・