%{
/*{{定型コード:lex.yy.l(定義部,%{〜%}内)=====================================*/
#ifdef  PIECE
#include "app.h"
#else //PIECE
#include "winapp.h"
#endif//PIECE
#include "y.tab.h"
/* 入力バッファサイズを定義します。
 * デフォルトでは16384と定義されており、P/ECEには大きすぎます。
 * P/ECEに適切な、小さなサイズ(256)に、再定義しました。
 * 入力バッファサイズが不足した場合は、自動的に拡張されるので、問題ありません。
 * 一つのトークンの大きさが、入力バッファサイズを超えたときに、拡張されるようです。
 */
#undef  YY_BUF_SIZE
#define YY_BUF_SIZE 256
/* 入力ファイルの行を数えるための変数を定義します。
 * 「%option yylineno」を指定して、行を数えるコードを自動生成することもできますが、
 * コンパイラが警告を出したりして煩わしくなるので、自分で数えることにしました。
 */
int yylineno;
/* スキャナの入力ファイルを初期化します。
 * yyparse()を実行する都度、その直前に、本関数を呼び出してください。
 */
void yylex_init(FILE* input_file) {
  if(!input_file) DIE();   /* 入力ファイルが指定されていなければエラー停止 */
  BEGIN INITIAL;           /* スタート状態を初期化します */
  yylineno = 1;            /* 入力ファイルの行を初期化します */
  yyrestart(input_file); } /* スキャナの実行を再開するようFlexに通知します */
/* 入力方法を変更するマクロを定義します。
 * lex.yy.c内で、デフォルトのYY_INPUT()よりも先に展開されるので、#undefは不要です。
 * 自作CLiPライブラリの標準入出力は、CRLFをLFに変換しないので、明示的に変換します。
 * * Wed Jul 01 21:52:52 JST 2015 Naoyuki Sawa
 * - 行末のバックスラッシュで行継続する機能を追加しました。
 *   有限状態機械マップスクリプトはCプリプロセッサと相性が悪く、当ツールにかける前にCプリプロセッサを通してCプリプロセッサによる行継続を適用する事が難しい事が判ったからです。
 *   有限状態機械マップスクリプト内の'%{〜%}'の中でCプリプロセッサ疑似命令を使用していると、Cソースファイルに出力する前に展開されてしまい、予期しない結果になるからです。
 *   上記の問題を避けるため、当ツール自体に、行末のバックスラッシュで行継続する機能を追加する事にしました。
 * - '%{〜%}','[`〜`]','{`〜`}'の中は、字句解析によって行継続しますので、行末のバックスラッシュ指定は不要です。
 */
#define YY_INPUT(buf,result,max_size) {						\
  int i = 0; while(i < (max_size)) {						\
    int c = getc(yyin);								\
    if(c == EOF ) { break; }							\
    if(c == '\r') { continue; }							\
    if(c == '\\') { int d = getc(yyin);						\
                    if(d == '\r') { d = getc(yyin); }				\
                    if(d == '\n') { c = ' '; } else { ungetc(d, yyin); } }	\
    (buf)[i++] = c;								\
    if(c == '\n') { yylineno++; break; }					\
  } (result) = i; }
/*}}定型コード:lex.yy.l(定義部,%{〜%}内)=====================================*/
%}
/*{{定型コード:lex.yy.l(定義部,%{〜%}外)=====================================*/
/* Suppress the appearance of unneeded routines in the generated scanner. */
%option noinput
%option nounput
/* Make the scanner not call yywrap() upon an end-of-file, but simply assume that there are no more files to scan. */
%option noyywrap
/*}}定型コード:lex.yy.l(定義部,%{〜%}外)=====================================*/

%x COMMENT
%x SOURCE
%x CODE

mbblead		([\x81-\x9F]|[\xE0-\xFC])
mbbtrail	([\x40-\x7E]|[\x80-\xFC])

%%

<INITIAL>{
"#"				{ BEGIN COMMENT; }
"%{"				{ BEGIN SOURCE; }
\`				{ BEGIN CODE; }

"["				|
"]"				|
"{"				|
"}"				|
"("				|
")"				{ return yytext[0]; }

"enter"				{ return T_ENTER; }
"leave"				{ return T_LEAVE; }
"push"				{ return T_PUSH; }
"pop"				{ return T_POP; }
"end"				{ return T_END; }

[_[:alnum:]]+			{ yylval.v_str = strdup(yytext); return T_LAB; }	/* 当ツールは数値リテラルを使用しないので、数字から始まるラベルも「`」無しで書ける事にした。「`」は別の用途でコードを括るために使用する。 */

[[:blank:]]+			{ /** no job **/ }
\n				{ return T_EOL; }
.				{ yyerror("scan error"); return yytext[0]; }
}

<COMMENT>{
\n				{ BEGIN INITIAL; return T_EOL; }
.				{ /** no job **/ }
}

<SOURCE>{
<<EOF>>				{ BEGIN INITIAL; yyerror("EOF in source."); yynerrs++; }
"%}"				{ BEGIN INITIAL; yytext[yyleng - 2] = '\0'; yylval.v_str = strdup(yytext); return T_SOURCE; }
\n|.				{ yymore(); }
}

<CODE>{
<<EOF>>				{ BEGIN INITIAL; yyerror("EOF in code."); yynerrs++; }
\`				{ BEGIN INITIAL; yytext[yyleng - 1] = '\0'; yylval.v_str = strdup(yytext); return T_CODE; }
{mbblead}{mbbtrail}		|	/* `…`の中ではシフトJISを意識したスキャンを行う。最長一致のルールにより上の行の「\`」よりもこの行が優先される。 */
\n|.				{ yymore(); }
}

%%
