|
|
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
という風にしたいです。
|
|
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の方向性ではそういったものは作ることは出来ないと考えた方が良いかと思います。
ロマンはあります、ロマンは…。
|
|
2020/1/4(Sat) 06:32:46|NO.89163
おはようございます
自分は、全然、コードに落とせてないんでアレなんですが
小型の言語はスタックマシンがいいとされていて
何らかをスタックに積む命令と 積まれているスタックから二つ取り出して表示する命令に
分けたらどうですか?
push 1
push "あ\n"
test
// test命令
mes pop
mes pop
みたいかんじで
引数に文字列と数値が混ざっているんで
スタックもモジュール変数を利用するか
全部、文字列として扱うかするかが必要っすね
|
|
2020/1/4(Sat) 13:28:39|NO.89167
返信ありがとうございます。
「test ("A",B)」と打ち込むのではなく、
「
test
あ
1
fend
」
という風に他のプログラミング言語とは違う形ですることにしました。
|
|
2020/1/4(Sat) 13:30:52|NO.89168
あと、特定の文字を認識して、色分けすることは可能ですか?
何度も質問してごめんなさい
|
|
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)

| |
|
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の間違いじゃないですか?
|
|
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
にすれば複数回使えます。
だけどこのアルゴリズムだと命令追加するときが大変なので、
他のアルゴリズムを考えておきます。

| |
|
2020/1/4(Sat) 20:21:12|NO.89175
こんばんわ
自分、詳しくないっすけど
footy2を使うとキーワードの色変えれるっぽいイメージです
今となっては配布先探すのも大変ですし
スキルがないと使いこなせないかんじっすね
(僕には使いこなせません)
TeraPadとかさくらエディタで配色変えるくらいで落としどころとするのが
良さげだと思います
公式エディタでも配色変えれば気分変わるかもっすね
自分は背景、紺色となっております
知ってたらごめんなさいで
ツール→オプション→エディタ→フォント/色/表示
らへんです
|
|
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
|
|
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); // 現在のカーソル位置取得
|
|
2020/1/5(Sun) 07:48:58|NO.89183
皆さんありがとうございます。
助かりました!!
|
|
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となっています。

| |
|
2020/1/5(Sun) 12:56:08|NO.89186
正規表現のモジュールの中身見てたらマッチした結果を配列で受け取る命令あったので、
それを使うように書き換えたければ
モジュールを読み込んで、
Match block,".+\\n.+\\n.+\\/",re
の行を
matches re,block,".+\\n.+\\n.+\\/"
に書き換えれば大丈夫です。
ただ、モジュールの中の命令を今後使うつもりがないなら
この書き換えはいらないと思います。
しかし、今のままではhspでいうrepeat文とかif文を追加できないので
上記の書き換えはした方がいいと思います。
|
|
2020/1/5(Sun) 17:52:17|NO.89187
こんばんわ
>という風に他のプログラミング言語とは違う形ですることにしました。
何気にものすごい発言しましたな
でも、普通の言語は共通点多くて
小型の言語の方が自由度大きそうですね
参考になります
それでは、応援してます。頑張ってください。
|
|
2020/1/6(Mon) 06:25:31|NO.89190
ありがとうございます!!
|
|
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でテキスト解析していくものは知ってますけど
|
|
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, "もふもふ")
"}

| |
|