言語依存データの外部ファイル化について考える その2
とりあえず字句解析します。
ダブルクオート(")の中では'\'をエスケープ文字としますが'\'の次の文字列そのものを有効にする機能以外はサポートしません、例えば"\n"とか"\t"とか"\045"や"\u2191"とかです。あと文字列長チェックが必要ですが、とりあえずテストなのでチェックしていません。
昔の記憶を思い出しながら、langfile.lex を書いてみました。
/* -*- mode: c; coding: utf-8-unix -*- */ /* // -*- mode: c; coding: utf-8-unix -*- // Copyright (c) 2017 FunFun < fu.aba.dc5@gmail.com> // // for c : flex -o langfile.c langfile.lex ; gcc -o langfile langfile.c // for c++ : flex -+ -o langfile.cpp langfile.lex ; g++ -o langfile -I. langfile.cpp */ %{ #ifdef __FLEX_LEXER_H #include <cstdio> #else // __FLEX_LEXER_H #include <stdio.h> #endif // __FLEX_LEXER_H %} ws [ \t]+ comment #.* nl \n section \[[a-zA-Z]+\] key_id Key_[a-zA-Z0-9_]+ vk_id VK_[a-zA-Z0-9_]+ shiftkey SHIFTKEY_NEED|SHIFTKEY_NONEED|SHIFTKEY_THROUGH platform Windows|macOS|Linux string [a-zA-Z_]+ number [0-9]+ comma , equal = %x qstring %% char string_buf[1024]; char *string_buf_ptr; \" { string_buf_ptr = string_buf; BEGIN(qstring); } <qstring>\" { BEGIN(INITIAL); *string_buf_ptr = '\0'; printf("qstring = \"%s\"\n", string_buf); } <qstring>\\(.|\n) { *string_buf_ptr++ = yytext[1]; } <qstring>[^\\\n\"]+ { char *yptr = yytext; while (*yptr){ *string_buf_ptr++ = *yptr++; } } {ws} ; {comment} { printf("comment = %s\n", yytext); } {nl} ; {comma} ; {equal} ; {section} { printf("section = %s\n", yytext); } {key_id} { printf("key_id = %s\n", yytext); } {vk_id} { printf("vk_id = %s\n", yytext); } {shiftkey} { printf("shiftkey = %s\n", yytext); } {platform} { printf("platform = %s\n", yytext); } {string} { printf("string = %s\n", yytext); } {number} { printf("number = %s\n", yytext); } %% /* for TEST */ #ifdef __FLEX_LEXER_H /* for C++ */ int yyFlexLexer::yywrap() { return 1; } int main(int argc, char *argv[]) { yyFlexLexer lexer; lexer.yylex(); } #else // __FLEX_LEXER_H /* for C */ int yywrap() { return 1; } int main(int argc, char *argv[]) { yylex(); } #endif // __FLEX_LEXER_H
標準入力から Japanese.lng を読み込ませるとこんな出力になります。
comment = # japanese keyboard layout comment = # Copyright (c) 2017 FunFuncomment = # spec version 1 section = [General] string = Name qstring = "Japanese" string = Author qstring = "FunFun <fu.aba.dc5@gmail.com>" string = SpecVersion number = 1 section = [Keys] key_id = Key_Escape vk_id = VK_ESCAPE shiftkey = SHIFTKEY_THROUGH key_id = Key_Tab vk_id = VK_TAB shiftkey = SHIFTKEY_THROUGH key_id = Key_Backspace vk_id = VK_BACK shiftkey = SHIFTKEY_THROUGH key_id = Key_Return vk_id = VK_RETURN shiftkey = SHIFTKEY_THROUGH key_id = Key_Enter vk_id = VK_RETURN shiftkey = SHIFTKEY_THROUGH key_id = Key_Insert vk_id = VK_INSERT shiftkey = SHIFTKEY_THROUGH : 後略
なんとなく字句解析は出来ていそうです。
"SHIFTKEY_NEED", "SHIFTKEY_NONEED", "SHIFTKEY_THROUGH", "Windows", "macOS", "Linux" は予約語扱いになります。 "VK_" や "Key_" で始まるものは仮想キーコード、Qtのキー定数とみなしてチェックしますので、不正なものはエラーとする必要があります。
flex は C と C++ のコードを生成できるので、上記 lex コードの実行はどちらでも可能です。出来れば C++ コードで生成して利用したいのですが、macOS 上の clang だとなんかコンパイルエラーになるんですよね…なんででしょう?
(追記)
初回起動時に .lng を解析してバイナリファイルを作成し、実際はこのバイナリファイルを読み込もうかと思います。その場合、.lng が更新されていたら、再解析してバイナリファイルを作成し直す必要がありますねぇ。オプションにしましょうかね…
« Android APK の準備 その2 | トップページ | 言語依存データの外部ファイル化について考える その3 »
« Android APK の準備 その2 | トップページ | 言語依存データの外部ファイル化について考える その3 »
コメント