« Android APK の準備 その2 | トップページ | 言語依存データの外部ファイル化について考える その3 »

2017年3月19日 (日)

言語依存データの外部ファイル化について考える その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 FunFun 
comment  = # 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 »

コメント

コメントを書く

コメントは記事投稿者が公開するまで表示されません。

(ウェブ上には掲載しません)

トラックバック


この記事へのトラックバック一覧です: 言語依存データの外部ファイル化について考える その2:

« Android APK の準備 その2 | トップページ | 言語依存データの外部ファイル化について考える その3 »