;;; @file    regexp.nsc
;;; @brief   senzogawa作「nscronig.dll」のラッパ
;;; @desc    ・適切な「番号.txt」に名前を変えて使用してください。
;;;          ・変数番号の先頭は REGEXP_ARG_BEGIN で指定できます。
;;;          ・変数番号の末尾は REGEXP_ARG_END で定義されます。
;;;          ・「nscronig.dll」をカレントディレクトリ以外に置く場合は、
;;;            REGEXP_DLL にディレクトリ名を指定してください。
;;;            その際、パス区切りには「\」を用いてください。
;;; @version 1.0(nscronig.dll Ver.0.0, NScripter Ver.2.82)
;;; @author  senzogawa
*regexp_plugin
stralias REGEXP_DLL,"nscronig.dll"
numalias REGEXP_ARG_BEGIN,190
stralias REGEXP_PARAM_SEP,"|"

; 付加設定を複数指定する場合はREGEXP_PARAM_SEPで区切ること。
stralias REGEXP_OPTION_NONE,               ""  ; オプションなし
stralias REGEXP_OPTION_SINGLELINE,         "s" ; '^' -> '\A', '$' -> '\Z'
stralias REGEXP_OPTION_MULTILINE,          "m" ; '.'が改行にマッチする
stralias REGEXP_OPTION_IGNORECASE,         "i" ; 曖昧マッチ オン
stralias REGEXP_OPTION_EXTEND,             "e" ; パターン拡張形式
stralias REGEXP_OPTION_FIND_LONGEST,       "l" ; 最長マッチ
stralias REGEXP_OPTION_FIND_NOT_EMPTY,     "n" ; 空マッチを無視
stralias REGEXP_OPTION_DONT_CAPTURE_GROUP, "g" ; 名前付き捕獲式集合のみ捕獲
stralias REGEXP_OPTION_CAPTURE_GROUP,      "G" ; 名前無し捕獲式集合も捕獲

defsub regexp_match
defsub regexp_matchex
defsub regexp_find
defsub regexp_findex
defsub regexp_getfoundstr
defsub regexp_findeach
defsub regexp_findeachex
defsub regexp_eachbreak
defsub regexp_exec
defsub regexp_execwith
;// private
defsub regexp_callproc

mov %0,REGEXP_ARG_BEGIN
numalias regexp_command,%0:inc %0
numalias regexp_options,%0:inc %0
numalias regexp_param,%0:inc %0
numalias regexp_pattern,%0:inc %0
numalias regexp_proc,%0:inc %0
numalias regexp_result,%0:inc %0
numalias regexp_text,%0:inc %0
numalias regexp_break,%0:inc %0
numalias REGEXP_ARG_END,%0-1
return


;;; @brief 正規表現に適合するか確認する。
;;; @usage regexp_match %結果, 検索対象文字列, 正規表現文字列
;;; @note  適合するなら1、不適合なら0を返す。
*regexp_match
getparam i%regexp_result,$regexp_text,$regexp_pattern
regexp_matchex %%regexp_result,$regexp_text,$regexp_pattern,""
return


;;; @brief 正規表現に適合するか確認する。(付加設定)
;;; @usage regexp_matchex %結果, 検索対象文字列, 正規表現文字列, 付加設定
;;; @note  適合するなら1、不適合なら0を返す。
*regexp_matchex
getparam i%regexp_result,$regexp_text,$regexp_pattern,$regexp_options
regexp_execwith "setPattern",$regexp_pattern
regexp_execwith "setOption",$regexp_options
regexp_execwith "find",$regexp_text
getret %regexp_text
getret $regexp_result
regexp_exec "end"
if %regexp_text<0 mov %%regexp_result,0:return
mov %%regexp_result,1
return


;;; @brief 正規表現で検索する。
;;; @usage regexp_find %先頭位置, 検索対象文字列, 正規表現文字列
;;; @note  先頭位置は0オリジン。見つからない場合は負値。
*regexp_find
getparam i%regexp_result,$regexp_text,$regexp_pattern
regexp_findex %%regexp_result,$regexp_text,$regexp_pattern,""
return


;;; @brief 正規表現で検索する。(付加設定)
;;; @usage regexp_findex %先頭位置, 検索対象文字列, 正規表現文字列, 付加設定
;;; @note  先頭位置は0オリジン。見つからない場合は負値。
*regexp_findex
getparam i%regexp_result,$regexp_text,$regexp_pattern,$regexp_options
regexp_execwith "setPattern",$regexp_pattern
regexp_execwith "setOption",$regexp_options
regexp_execwith "find",$regexp_text
getret %%regexp_result
getret $regexp_result
regexp_exec "end"
return


;;; @brief 適合した文字列を取得する。
;;; @usage regexp_getfoundstr $適合文字列
;;; @note  最後の結果をそのまま返すので、find後に呼び出さないと意味はない。
*regexp_getfoundstr
getparam s%regexp_result
mov $%regexp_result,$regexp_result
return


;;; @brief 正規表現の適合ごとに処理する。
;;; @usage regexp_findeach *コールバック, 検索対象文字列, 正規表現文字列
;;; @note  検索を実行し、適合するごとにコールバックを呼び出す。
;;; @desc
;;; コールバック:
;;;   引数は 検索対象文字列, 先頭位置, 適合文字列 を渡す。
;;;   1件も適合しない場合は一度も呼び出されない。
;;;   内部での regexp_findeach の呼び出しは不可
*regexp_findeach
getparam $regexp_proc,$regexp_text,$regexp_pattern
regexp_findeachex $regexp_text,$regexp_pattern,$regexp_proc,""
return


;;; @brief 正規表現の適合ごとに処理する。(付加設定)
;;; @usage regexp_findeachex *コールバック, 検索対象文字列, 正規表現文字列, 付加設定
;;; @note  検索を実行し、適合するごとにコールバックを呼び出す。
;;; @desc
;;; コールバック:
;;;   引数は 検索対象文字列, 先頭位置, 適合文字列 を渡す。
;;;   1件も適合しない場合は一度も呼び出されない。
;;;   内部での regexp_findeach の呼び出しは不可
*regexp_findeachex
getparam $regexp_proc,$regexp_text,$regexp_pattern,$regexp_options
regexp_execwith "setPattern",$regexp_pattern
regexp_execwith "setOption",$regexp_options
regexp_execwith "find",$regexp_text
mov %regexp_break,0
*regexp_findeach_loop
getret %regexp_result
getret $regexp_result
if %regexp_result>=0 regexp_callproc $regexp_proc $regexp_text,%regexp_result,$regexp_result
if %regexp_break==0 && %regexp_result>=0 regexp_exec "next":goto *regexp_findeach_loop
regexp_exec "end"
return


;;; @brief 連続検索処理を途中で終了する。
;;; @usage regexp_eachbreak
;;; @note  regexp_findeach, regexp_findeachexのコールバック内部で呼び出すことを想定。
*regexp_eachbreak
mov %regexp_break,1
return


;;; @brief regexpプラグインを実行する。
;;; @usage regexp コマンド
;;; @note  
*regexp_exec
getparam $regexp_command
exec_dll REGEXP_DLL+"/"+$regexp_command
return


;;; @brief regexpプラグインを引数付で実行する。
;;; @usage regexp コマンド, パラメータ
;;; @note  パラメータの区切りはREGEXP_PARAM_SEPを用いる。
*regexp_execwith
getparam $regexp_command,$regexp_param
exec_dll REGEXP_DLL+"/"+$regexp_command+" "+$regexp_param
return


;// private

;;; コールバックを呼び出す。
*regexp_callproc
getparam $regexp_proc
goto $regexp_proc