HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2020
0103
HSP 初心者HSP テキストファイル引数21解決


HSP 初心者

リンク

2020/1/3(Fri) 20:06:49|NO.89156

https://hsp.tv/play/pforum.php?mode=all&num=88687

前に「HSPでプログラミング言語自作」というものを投稿したのですが
命令の引数のところがよくわからないので、教えてください!



まず、test.txtというファイルを作成して
「 test ("あ",1)  」
と打ち込んで
そのtextファイルをHSPに読みこんで
画面上に
「あ
1 」
と出るようにしたいです


要するに
test ("A",B) → mes ""+A\nB
という風にしたいです。



この記事に返信する


AAA

リンク

2020/1/3(Fri) 23:46:37|NO.89162

そのリンク先にある
http://hsp.tv/play/pforum.php?mode=pastwch&num=42969

そこでのf様の説明で作ることが出来ないならかなり難しいかと思いますが…
まずはINIファイルのパーサー辺りを作る練習をされてみてはいかがでしょうか?
GetPrivateProfileStringという激烈に遅い32APIに頼らず自分でnotesel noteload getstrを使い作ります。
getstrです。
notegetは使ってはいけません、アレは何故存在しているのかわからない詐欺命令だとご理解ください。
それがクリア出来れば HSP INIモジュールで引っかかってくるものより数十倍〜数百倍近くも速いものが
出来上がり質問者様のやりたいことも簡単に行えるようになります。

但し、それでもC(だけではないですが)で同じことをされると更に数十倍以上も速くされてしまいます。

つまるところHSPでやるには根本的に遅すぎて問題外という事です。
ロマンはありますがswitch一つとっても世界一頭の悪いソースコードと晒し上げられている『if文連打』
を超えるおかしな謎仕様を取り込むHSPの方向性ではそういったものは作ることは出来ないと考えた方が良いかと思います。
ロマンはあります、ロマンは…。



Y_repeat

リンク

2020/1/4(Sat) 06:32:46|NO.89163

おはようございます

自分は、全然、コードに落とせてないんでアレなんですが

小型の言語はスタックマシンがいいとされていて
何らかをスタックに積む命令と 積まれているスタックから二つ取り出して表示する命令に
分けたらどうですか?

push 1
push "あ\n"
test

// test命令
mes pop
mes pop

みたいかんじで

引数に文字列と数値が混ざっているんで
スタックもモジュール変数を利用するか
全部、文字列として扱うかするかが必要っすね



HSP 初心者

リンク

2020/1/4(Sat) 13:28:39|NO.89167

返信ありがとうございます。

「test ("A",B)」と打ち込むのではなく、



test

1
fend



という風に他のプログラミング言語とは違う形ですることにしました。



HSP 初心者

リンク

2020/1/4(Sat) 13:30:52|NO.89168

あと、特定の文字を認識して、色分けすることは可能ですか?
何度も質問してごめんなさい



HSP 初心者

リンク

2020/1/4(Sat) 15:32:54|NO.89170

自分なりにプログラミング言語を作ろうとしてみましたが
同じ関数を二回使うことができなくなってしまいました

こちらも教えてください


;onerror *er #include "mod_regexp.as" title "SS言語" bgscr 0,1920,1080,0,0,0 color 60,60,60 boxf color 30,30,30 boxf 0,0,1920,80 color 255,255,255 font "msgothic",80 mes "SS言語" buffer 1 screen 1,640,480 color 255,0,0 boxf color 255,255,255 font "Marlett",80 mes "r" buffer 2 screen 2,640,480 color 255,125,0 : boxf font "msgothic",80 color 255,255,255 mes "実行" gsel 0 objmode 2,0 objimage 1,0,0,0,0,0,0 objsize 80,80 pos 1920-80,0 button "",*ends objimage 2 objsize 160,80 pos 800,0 button "",*zikkou main = "" pos 0,80 mesbox main,1920,1000 stop *ends end stop *zikkou if main = "" : dialog "プログラムを入力していません",1 : stop notesel main noteget main1,1 NWSG = notefind("newscreen",1) STIG = notefind("scrtit",1) texg = notefind("text",1) if NWSG = -1 { NWSG2 = notefind("newscreen",2) if NWSG2 = -1 :else :dialog "「newscreen」エラー\n命令は行の初めに打ち込んでください。",1 }else{ screen 3 onexit *endk } if STIG = -1 { STIG2 = notefind("scrtit",2) if STIG2 = -1 :else :dialog "「scrtit」エラー\n命令は行の初めに打ち込んでください。",1 }else{ STIG3 = notefind("scrtit/",1) if STIG+2 = STIG3 :noteget TITLENAME,STIG3-1 if NWSG = -1 : dialog "「scrtit」エラー\n「newscreen」が見つかりません ":else{ gsel 3,1 title ""+TITLENAME onexit *endk } } if texg = -1 { texg2 = notefind("scrtit",2) if texg2 = -1 :else:dialog "「text」エラー\n命令は行の初めに打ち込んでください。",1 }else{ texg3 = notefind("text/",1) if texg+2 = texg3 : noteget textNAME,texg3-1 if NWSG = -1 : dialog "「text」エラー\n「newscreen」が見つかりません ":else{ gsel 3,1 print textNAME } } stop *endk if (ginfo_act == 0) { end }else { gsel ginfo_act,-1 } stop *er dialog "エラーが発生しました\n エラーコード:"+strf("[%#x]",err*100)



HSP 初心者

リンク

2020/1/4(Sat) 15:37:49|NO.89171

↑↑↑

サンプルコード

関数を一回ずつ使う

newscreen scrtit タイトル scrtit/ text テキスト text/


関数を2回ずつ使う


newscreen scrtit タイトル scrtit/ scrtit タイトル2 scrtit/ text テキスト text/ text テキスト2 text/



ソラ

リンク

2020/1/4(Sat) 16:26:50|NO.89172

94行目の
texg2 = notefind("scrtit",2)
これ、p1はtextの間違いじゃないですか?



kanamaru

リンク

2020/1/4(Sat) 17:33:21|NO.89173

複数回使えないのは、notefindを使ってるからです。
notefindは見つかった最初の行しか調べません。
なので命令を使った最初の一回しか処理しません。
*zikkouラベルを

*zikkou dum=main strrep dum,"\n","" if dum = "" : dialog "プログラムを入力していません",1 : stop notesel main newscreen=0 scrtit=0 text=0 tline=0 mline=0 repeat notemax noteget main2,cnt if(main2="newscreen"){ screen 3 pos 0,0 color 0,0,0 newscreen=1 }else:if(main2="scrtit"){ if(newscreen=0){ dialog "「scrtit」エラー\n「newscreen」が見つかりません " } if(scrtit=0){ scrtit=1 }else{ dialog "line:"+(cnt+1)+"\n既に実行しています。",1 } if(text=1){ dialog "line:"+(cnt+1)+"\n「text]を既に実行しています。",1 } }else:if(main2="text"){ if(newscreen=0){ dialog "「text」エラー\n「newscreen」が見つかりません " } if(text=0){ text=1 }else{ dialog "line:"+(cnt+1)+"\n既に実行しています。",1 } }else:if(main2="scrtit/"){ if(newscreen=0){ dialog "「scrtit」エラー\n「newscreen」が見つかりません " } if(scrtit=1){ scrtit=0 tline=0 }else{ dialog "line:"+(cnt+1)+"\n既に実行しています。",1 } }else:if(main2="text/"){ if(newscreen=0){ dialog "「text」エラー\n「newscreen」が見つかりません " } if(text=1){ text=0 mline=0 }else{ dialog "line:"+(cnt+1)+"\n既に実行しています。",1 } }else{ if(scrtit=1){ if(tline=0){ title ""+main2 }else{ dialog "line:\n「scrtit」エラー\n複数行表示できません" } tline++ }else:if(text=1){ if(mline=0){ gsel 3,1 mes main2 }else{ dialog "line:\n「text」エラー\n複数行表示できません" } }else{ if(main2!""):dialog "line:"+(cnt+1)+"\n命令を実行していません" } } await 1 loop stop
にすれば複数回使えます。
だけどこのアルゴリズムだと命令追加するときが大変なので、
他のアルゴリズムを考えておきます。



Y_repeat

リンク

2020/1/4(Sat) 20:21:12|NO.89175

こんばんわ

自分、詳しくないっすけど
footy2を使うとキーワードの色変えれるっぽいイメージです
今となっては配布先探すのも大変ですし
スキルがないと使いこなせないかんじっすね
(僕には使いこなせません)

TeraPadとかさくらエディタで配色変えるくらいで落としどころとするのが
良さげだと思います
公式エディタでも配色変えれば気分変わるかもっすね
自分は背景、紺色となっております

知ってたらごめんなさいで
ツール→オプション→エディタ→フォント/色/表示
らへんです



Y_repeat

リンク

2020/1/4(Sat) 20:59:10|NO.89176

>命令は行の初めに打ち込んでください。
と書いてあったので命令の前後のスペースとタブを削除するスクリプトを書いてみました
*zikkouする前に一回動かしとくといいかと

main=" newscreen\n scrtit\n タイトル\n scrtit/\n" main+="scrtit \n タイトル2\nscrtit/ \n" main+=" text \n テキスト\n text/ \n" main+=" text \n テキスト2 \n text/ " notesel main repeat notemax noteget get,cnt moto = get target=moto target_moto=target //左側のタブとスペース削除 while 1 target=strtrim(target,1,' ') target=strtrim(target,1,'\t') if target==target_moto:_break target_moto=target await 1 wend //右側のタブとスペース削除 target_moto=target while 1 target=strtrim(target,2,' ') target=strtrim(target,2,'\t') if target==target_moto:_break target_moto=target await 1 wend //文字列がキーワードじゃなかったら、元の文字列に戻す if target=="newscreen"||target=="scrtit"||target=="scrtit/"||target=="text"||target=="text/"{ }else{ target=moto } noteadd target,cnt,1 loop mes main



HSP 初心者

リンク

2020/1/4(Sat) 22:34:04|NO.89178

返信ありがとうございます

あとで試してみます



あらや

リンク

2020/1/4(Sat) 23:47:13|NO.89180

文字の色分けはかなり面倒だと思いますが
前にHTMLタグの色分けをした時のソースがありますのでご参考に
http://hsp.tv/play/pforum.php?mode=pastwch&num=84430

そして今更ですが……
リンク先のタグの色分け処理の最初の箇所の記述が間違っていました。

sendmsg hRich, EM_GETSEL, pStart, pEnd; // 現在のカーソル位置取得

正確にはこうでした<(_ _)>

sendmsg hRich, EM_GETSEL, varptr(pStart), varptr(pEnd); // 現在のカーソル位置取得



HSP 初心者

リンク

2020/1/5(Sun) 07:48:58|NO.89183

皆さんありがとうございます。
助かりました!!



kanamaru

リンク

2020/1/5(Sun) 12:40:08|NO.89185

解決済みにしたようですが、以前言ったように、
命令を追加するときが大変なのでアルゴリズムを改良しました。
その前に、正規表現を使うモジュールを読み込んでいるようですが、
そのモジュールを読み込む代わりに

#module #deffunc Match str buf, str pattern,array re newcom oReg, "VBScript.RegExp" comres result oReg("Pattern")= pattern oReg("Global")= 1 oReg->"Execute" buf oMatches=result rt = oMatches("Count") if(rt>0){ repeat rt oMatch=oMatches("Item",cnt) //Matchdata.0 = oMatch("Value") //Matchdata.1 += Matchdata.0 //Matchdata.0 = "" re(cnt)=oMatch("Value") loop //buf = Matchdata.1 delcom oMatch delcom oMatches } delcom oReg delcom result return rt #global
を追加してください。
(なぜかというと、そのモジュールのMatch命令は
マッチした最初の一個しかわからないのでマッチしたのを配列でほしかったからです。)
それで、*zikkouラベルを

*zikkou split main,"newscreen",main2 foreach main2 block=main2(cnt) strrep block,"\n","" strrep block,"\t","" strrep block," ","" if(block=""):continue if(cnt=0):dialog "エラー newscreenが見つかりません",2 screen 3 onexit *endk block=main2(cnt) Match block,".+\\n.+\\n.+\\/",re foreach re split re(cnt),"\n",bl if(stat!3):dialog "「"+bl(0)+"」エラー\n複数行は対応していません。",2 if(bl(0)+"/"!bl(2)):dialog "「"+bl(0)+"」エラー\n命令の開始と終わりが対応していません。",2 if(bl(0)="scrtit"){ gsel 3,1 title bl(1) }else:if(bl(0)="text"){ gsel 3,1 mes bl(1) } await 1 loop await 1 loop stop
に変えてください。
これで命令を複数回呼べますし、
命令を追加したいときは、
if文を追加してください。
switch文使いたかったらご自由にどうぞ。
bl(0)に命令が、bl(1)に引数が入っています。
今のプログラムでは引数は一個で固定になっています。
引数を二個以上つかいたいときは、
if(stat!3):dialog "「"+bl(0)+"」エラー\n複数行は対応していません。",2
の行を消して、
各命令の中で
if(length(bl)!3):dialog "「"+bl(0)+"」エラー\n引数の数が違います。",2
等としてください。
bl配列の長さは引数の数+2となっています。



kanamaru

リンク

2020/1/5(Sun) 12:56:08|NO.89186

正規表現のモジュールの中身見てたらマッチした結果を配列で受け取る命令あったので、
それを使うように書き換えたければ
モジュールを読み込んで、
Match block,".+\\n.+\\n.+\\/",re
の行を
matches re,block,".+\\n.+\\n.+\\/"
に書き換えれば大丈夫です。
ただ、モジュールの中の命令を今後使うつもりがないなら
この書き換えはいらないと思います。
しかし、今のままではhspでいうrepeat文とかif文を追加できないので
上記の書き換えはした方がいいと思います。



Y_repeat

リンク

2020/1/5(Sun) 17:52:17|NO.89187

こんばんわ

>という風に他のプログラミング言語とは違う形ですることにしました。
何気にものすごい発言しましたな
でも、普通の言語は共通点多くて
小型の言語の方が自由度大きそうですね
参考になります

それでは、応援してます。頑張ってください。



HSP 初心者

リンク

2020/1/6(Mon) 06:25:31|NO.89190

ありがとうございます!!



HSP 初心者

リンク

2020/1/6(Mon) 06:37:09|NO.89191

皆さんが教えてくれたソースコードをまとめてみました


#module #deffunc Match str buf, str pattern,array re newcom oReg, "VBScript.RegExp" comres result oReg("Pattern")= pattern oReg("Global")= 1 oReg->"Execute" buf oMatches=result rt = oMatches("Count") if(rt>0){ repeat rt oMatch=oMatches("Item",cnt) //Matchdata.0 = oMatch("Value") //Matchdata.1 += Matchdata.0 //Matchdata.0 = "" re(cnt)=oMatch("Value") loop //buf = Matchdata.1 delcom oMatch delcom oMatches } delcom oReg delcom result return rt #global ;onerror *er title "SS言語" bgscr 0,1920,1080,0,0,0 color 60,60,60 boxf color 30,30,30 boxf 0,0,1920,80 color 255,255,255 font "msgothic",80 mes "SS言語" buffer 1 screen 1,640,480 color 255,0,0 boxf color 255,255,255 font "Marlett",80 mes "r" buffer 2 screen 2,640,480 color 255,125,0 : boxf font "msgothic",80 color 255,255,255 mes "実行" gsel 0 objmode 2,0 objimage 1,0,0,0,0,0,0 objsize 80,80 pos 1920-80,0 button "",*ends objimage 2 objsize 160,80 pos 800,0 button "",*zikkou main = "" pos 0,80 mesbox main,1920,1000 stop *ends end stop *zikkou split main,"newscreen",main2 foreach main2 block=main2(cnt) strrep block,"\n","" strrep block,"\t","" strrep block," ","" if(block=""):continue if(cnt=0):dialog "エラー newscreenが見つかりません",2 screen 3 onexit *endk block=main2(cnt) Match block,".+\\n.+\\n.+\\/",re foreach re split re(cnt),"\n",bl if(stat!3):dialog "「"+bl(0)+"」エラー\n複数行は対応していません。",2 if(bl(0)+"/"!bl(2)):dialog "「"+bl(0)+"」エラー\n命令の開始と終わりが対応していません。",2 if(bl(0)="scrtit"){ gsel 3,1 title bl(1) }else:if(bl(0)="text"){ gsel 3,1 mes bl(1) } await 1 loop await 1 loop stop *endk if (ginfo_act == 0) { end }else { gsel ginfo_act,-1 } stop *er dialog "エラーが発生しました\n エラーコード:"+strf("[%#x]",err*100)



実行してみたら

newscreenだけを使うことができませんでした。



嗚呼

リンク

2020/1/6(Mon) 19:12:04|NO.89193

これってインタープリターであるHSPでインタープリターをやろうということですよね
ナンセンスなことのように思います
スクリプトプレーヤーなどCでテキスト解析していくものは知ってますけど



HSP 初心者

リンク

2020/1/8(Wed) 07:41:49|NO.89199

kanamaruさんのソースを参考にさせてもらいました。


if dir_cmdline = "" { main = "" goto *startmain } title ""+dir_cmdline sdim filepath, 256 filepath = dir_cmdline ; テキストファイルの読み込み notesel main noteload strtrim(filepath, , '"'), 500 mes main *startmain #packopt icon "SSLicon.ico" #uselib "comdlg32.dll" #func GetSaveFileName "GetSaveFileNameA" sptr onexit *endk onerror *er #include "mod_regexp.as" title "SS言語" bgscr 0,1920,1080,0,0,0 color 60,60,60 boxf color 30,30,30 boxf 0,0,1920,80 color 255,255,255 font "msgothic",70 mes "SimpleScriptLanguage" buffer 1 color 255,0,0 boxf color 255,255,255 font "Marlett",80 mes "r" buffer 2 color 255,125,0 : boxf font "msgothic",80 color 255,255,255 mes "Run" buffer 3 color 128,0,128 : boxf font "msgothic",80 color 255,255,255 pos 90,0 mes "Save" buffer 4 color 128,128,255 : boxf font "msgothic",80 color 255,255,255 pos 90,0 mes "Load" gsel 0 objmode 2,0 objimage 1,0,0,0,0,0,0 objsize 80,80 pos 1920-80,0 button "",*ends objimage 2 objsize 160,80 pos 800,0 button "",*zikkou pos 1920-80-320,0 objimage 3,0,0,0,0,0,0 objsize 320,80 button "",*save pos 1920-80-640,0 objimage 4,0,0,0,0,0,0 objsize 320,80 button "",*load pos 0,80 mesbox main,1920,1000,5,0 stop *ends end stop *zikkou notesel main repeat notemax gy = cnt + 1 AAA = 0 notesel main noteget main2,cnt noteget main3,cnt+1 noteget main4,cnt+2 noteget main5,cnt+3 noteget main6,cnt+4 *newsc if(""+strtrim(main2, 2, ' ')+"") = ("newscreen") { onexit *endk screen 10 }else{ if (""+strtrim(main2, 2, ' ')+"") = ("text"){ if (""+strtrim(main4, 2, ' ')+"") = ("text/"){ pos PX,PY print main3 } if (""+strtrim(main6, 2, ' ')+"") = ("text/"){ if (""+strtrim(main3, 2, ' ')+"") = ("rep"){ repeat int(main4) pos PX,PY print main5 loop } } }else{ if (""+strtrim(main2, 2, ' ')+"") = ("scrtit"){ if (""+strtrim(main4, 2, ' ')+"") = ("scrtit/"){ title main3 } }else{ if (""+strtrim(main2, 2, ' ')+"") = ("pos"){ if (""+strtrim(main5, 2, ' ')+"") = ("pos/"){ PX = int(main3) : PY = int(main4) } } } } } loop stop *endk if (ginfo_act == 0) { end }else { gsel ginfo_act,-1 } stop *er dialog "エラーが発生しました\n エラーコード:"+strf("[%#x]",err*100) stop *save dialog "ssl",17 if stat = 1{ bsave refstr,main } stop *load dialog "ssl",16 if stat = 1 { bload refstr,main clrobj gsel 0 objmode 2,0 objimage 1,0,0,0,0,0,0 objsize 80,80 pos 1920-80,0 button "",*ends objimage 2 objsize 160,80 pos 800,0 button "",*zikkou pos 1920-80-320,0 objimage 3,0,0,0,0,0,0 objsize 320,80 button "",*save pos 1920-80-640,0 objimage 4,0,0,0,0,0,0 objsize 320,80 button "",*load pos 0,80 mesbox main,1920,1000,5,0 } stop



通りすがり

リンク

2020/1/8(Wed) 23:08:17|NO.89206

*newscのネスト地獄は命令が増えた時に困るので、else:ifかswitchを使った方がいいと思います。

どういった規模や用途の言語を作りたいのかわかりませんが、
四則演算や条件分岐に対応しようとすると、初心者が扱えない大きさのソースになります。
初心者の場合、ゲームのマップや敵データを読み込む処理あたりから始めるといい気がします。

こちらは一行一命令の仕様です。
#module "script"
#deffunc local parse_txt str _source sdim txt,strlen(_source) txt = _source parse@script txt return #deffunc local parse var _source split _source,"\n",txt repeat length(txt) : s_cnt = cnt : s_line = txt(cnt) //コマンド抽出 com_ed = instr(s_line,0,"(") if com_ed = -1 {//(が無ければ引数無しとする elem_st = -1 com_ed = strlen(s_line) }else{ elem_st = com_ed + 1 elem_ed = instr(s_line,elem_st,")") if elem_ed = -1 { logmes "()が閉じられていません。 行:"+ s_cnt +" 内容:"+ s_line : break } } com = strmid(s_line,0,com_ed) : strrep com," ","" : strrep com,"\t","" if strlen(com) = 0 : continue//命令が無ければ改行とみなして次の行へ //引数抽出 sdim arg : dim arg_type if elem_st != -1 { arg = strmid(s_line,elem_st,elem_ed) split arg,",",arg error = 0 repeat length(arg) str_st = instr(arg(cnt),0,"\"") if str_st = -1 { //文字列でなければ空白を消去 strrep arg(cnt)," ","" : strrep arg(cnt),"\t","" arg_type(cnt) = 0 }else{ //文字列なら""内の空白を保持して切り取る str_st += 1 str_ed = instr(arg(cnt),str_st,"\"") if str_ed = -1 { error = 1 : break } arg(cnt) = strmid(arg(cnt),str_st,str_ed) arg_type(cnt) = 1 } loop if error = 1 { logmes "\"\"が閉じられていません。 行:"+ s_cnt +" 内容:"+ s_line : break } } //解析 com_run@script com, arg, arg_type if stat != 0 { logmes "エラー行:"+ s_cnt +" 内容:"+ s_line : break } loop return 0 #deffunc local com_run var _com, array _arg, array _arg_type arg_num = length(_arg) if (arg_num = 1)&&(strlen(_arg) = 0)&&(_arg_type(0) = 0) : arg_num = 0//配列変数が空でも要素数が1を返す仕様の対策 //入力文字列の確認 logmes "[命令]"+ _com logmes "[引数]"+ arg_num repeat arg_num : logmes "type:"+ _arg_type(cnt) +" / elem:"+ _arg(cnt) : loop error = 0 switch _com case "newscreen" : if arg_num != 0 { error = 2 : swbreak } screen 10 : swbreak case "pos" : if arg_num != 2 { error = 2 : swbreak } PX = int(arg(0)) : PY = int(arg(1)) : swbreak case "text" if arg(0) = "rep" { if arg_num != 3 { error = 2 : swbreak } pos PX, PY : repeat limit(int(arg(1)),0,99) : mes arg(2) : loop }else{ if arg_num != 1 { error = 2 : swbreak } pos PX, PY : mes arg(0) } swbreak default : error = 1 : swbreak swend if error != 0 : error_msg@script error return error #deffunc local error_msg int _error logmes "エラー"+ _error switch _error case 1 : logmes "存在しない命令です。" : swbreak case 2 : logmes "引数の数が違います。" : swbreak default : logmes "解析エラー" : swbreak swend return #global parse_txt@script {" newscreen pos( 15, 50 ) text ("毛 玉 地 獄") pos (30,70) text (rep, 10, "もふもふ") "}



ONION software Copyright 1997-2023(c) All rights reserved.