stuncloud / UWSCR

UWSC互換スクリプト実行ツール
MIT License
54 stars 5 forks source link

「"」, 「( )」, 「[ ]」 欠落時の、エラー表示の行番号違い, 異常終了 等々の問題 #184

Open DIYJii opened 5 months ago

DIYJii commented 5 months ago

概要

ひょっとすると#181でトークン全般の問題として解決されているのかもしれませんが、Print文だけではなく、広範囲に及ぶ問題ですので、一応挙げておきます。症状は異なるものの、共通点が多いので、まとめてレポートします。

スクリプト上で、片方の「"」や「( )」や「[ ]」 が欠落している場合、

  1. MsgBox , FOPEN , EXEC, 三項演算子 では 間違ったエラー行番号と、それに伴って不適切なエラー内容が表示されます。単純なタイプ・ミスの結果ですので、行番号さえ合っていれば、全てのCaseでSyntax Errorとして貰ってもOKだと思います。

  2. Hoge = "a , Fuga[1] = "a , Dim hoge[] = "a では Error表示なく スクリプトがそこで実行終了します。

  3. Print "a では Error表示なく "a" とそれ以降の行に書かれているスクリプトを全部プリントします。

  4. If foge = "a  ではひたすら EndIf を書くよう、要求してきます。

  5. 但し上記2-4の問題は、後続のスクリプトに「"」が有れば、その行で下記の様にエラー表示されます    UWSCR構文エラー    test.uws[8, 8] - 文と同じ行に別の文が記述されています

全てに共通して、ペアーの右側トークンが欠落の場合、構文解析の折に、行を超えてペアーのトークンを探しに行き、 場合によってはペアーが見つからなくても、スクリプトの実行に移ってしまうケースが有る様です。 と云う事からすると、何か、前に有った行結合"_"の問題に絡んでいそうにも見えますが。

再現スクリプト

Case 1a
  MsgBOX("Ok?)

  EXIT
    test.uws[5, 1] - 不正なトークン(Eof); 期待されるトークンはRparen
    (注: LineNo 5,  Col 1, Eof ?)

Case 1b
  MsgBOX("Ok?"

  EXIT
    test.uws[3, 1] - 不正なトークン(Exit); 期待されるトークンはRparen
    (注: LineNo 3, Col 1, Exit ?)

Case 1c
  MsgBox(Ok?")

  EXIT
    test.uws[5, 1] - 不正なトークン(Eof); 期待されるトークンはColon
    (注: LineNo 5, Col 1, Eof, Colon ?)  

Case 1d
  MsgBox"Ok?")

  EXIT
    test.uws[1, 1] - 不正なトークンです: Identifier
    (注:Col 1, Identifier ?)

Case 1e
  ID = FOPEN("C:\Users\Public\Documents\Test.txt, F_READ)

  EXIT
    test.uws[3, 5] - 不正なトークン(Eof); 期待されるトークンはRparen

Case 1f
  ID = EXEC("C:\Users\Public\Documents\UWSCR.exe Test.uws)

  EXIT
    test.uws[3, 5] - 不正なトークン(Eof); 期待されるトークンはRparen

Case 1g
  a = 0
  Print a ? "a = True" :  "a = False
  MSGBOX("Ok?")
    test.uws[3, 8] - 文と同じ行に別の文が記述されています

///////////////////////////////////////

Case 2a
  hoge =  "a            //スクリプト終了
  MSGBOX(hoge)    

Case 2b
  fuga[1] =  "a        // スクリプト終了
  MSGBOX(fuga[1])

Case 2c
  dim hoge[]= "a      // スクリプト終了 
  MSGBOX(hoge[0])

///////////////////////////////////////

Case 3
  a = "Ok1"
  MSGBOX(a)           // Ok1 
  Print  "a           // a<#CR> MSGBOX(a)<#CR> b = a
  MSGBOX(a)
  b = a

////////////////////////////////////////

Case 4a
  hoge = "a"
  If  hoge = "a Then MSGBOX(hoge)
    test.uws[3, 1] - 不正なブロック終端(Eof); EndIfが必要です

Case 4b
  hoge = "a"
  If  hoge = "a Then 
    MSGBOX(hoge)
  EndIf
   test.uws[6, 1] - 不正なブロック終端(Eof); EndIfが必要です

Case 4c
  hoge = "a"
  If  hoge = "a Then 
    MSGBOX(hoge)
  EndIf
  EndIf
   test.uws[8, 44] - 不正なブロック終端(Eof); EndIfが必要です

再現手順

No response

バージョン

1.0.1

不具合発生環境

Windows 10

stuncloud commented 5 months ago

注意:以下で言う「トークン」とはLexerにより生成されるTokenを示し、issue本文に書かれている「トークン」とは意味が異なる

文字列トークンについて

Case別解説

Case 1

文末までが文字列扱いなため、次のトークンは関数呼び出しの閉じカッコ( ): Rparen ) であるべきだがEofであるというエラー 動作的には正常

Case 2b

通常なら次のトークンはEolなのでエラーとしてそれを示すが、関数のカッコ内は行跨ぎの記述を許容する(※)ためにEolを無視するので次のトークンはExitとなる 動作的には正常

// ※
msgbox(
    "こういう書き方ができる"
)

Case 1c

三項演算子となっていて、構文解析で

cond: Ok (識別子トークン) cons: Eofまでとなる文字列

までを解析したあと、alt部となる:トークンが存在しないためエラーとなる 動作的には正常

Case 1d

行頭にMsgBoxという識別子(Identifier)トークンがあり、それがいかなる式にもなり得ないため構文解析エラーとなっている、この行において以降の解析はスキップされるため"Ok")は無視されている 正常動作

Case 1e

Case 1f

Case 1aと同じ

Case 1g

181 と同様か、別の現象かも

これは要調査

Case 2a

Case 2b

Case 2c

いずれもCase 1aと同様 それぞれの代入式で"から文末までである文字列が代入されている

Case 3

Case 1aおよび2 と同様

Case 4a

Case 4b

Case 4c

いずれもthenを省略したif文扱いとなっている condはa = 文字列で、文字列が文末までなので次のトークンがEofとなり、そのためブロック文の閉じトークン(endif)がないというエラーになる 動作的には正常

対策について

確認

@DIYJii

以下のCaseにおいてエラーの行番号がスクリプトのどの行を示しているのか教えてください

DIYJii commented 5 months ago

今確認して、分かりました。 問い合わせのどのケースも、スクリプト・ファイルTest.uws上のスクリプトの後にあるブランクの行も含めた最終行がエラーの行番号として表示されています。 何度も、Test.uwsにテスト・ケースを書いたり、消したりたりしていますから、必ずしもレポートに載せたスクリプトの最終行ではなく、その後に続いていたブランク行も含めた最終行がエラーの行番号と表示されていた事になります。

On Mon, Jun 10, 2024 at 6:27 PM Joey Takahashi @.***> wrote:

注意:以下で言う「トークン」とはLexerにより生成されるTokenを示し、issue本文に書かれている「トークン」とは意味が異なる 文字列トークンについて

  • 字句解析において"及び'はペアができた時点で文字列トークンとするので、ペアにならなければEofまで行く
  • 文字列が閉じていないことを示す方法が現状ない

Case別解説 Case 1

文末までが文字列扱いなため、次のトークンは関数呼び出しの閉じカッコ( ): Rparen ) であるべきだがEofであるというエラー 動作的には正常 Case 2b

通常なら次のトークンはEolなのでエラーとしてそれを示すが、関数のカッコ内は行跨ぎの記述を許容する(※)ためにEolを無視するので次のトークンはExitとなる 動作的には正常

// ※msgbox( "こういう書き方ができる" )

Case 1c

三項演算子となっていて、構文解析で

cond: Ok (識別子トークン) cons: Eofまでとなる文字列

までを解析したあと、alt部となる:トークンが存在しないためエラーとなる 動作的には正常 Case 1d

行頭にMsgBox という識別子(Identifier)トークンがあり、それがいかなる式にもなり得ないため構文解析エラーとなっている、この行において以降の解析はスキップされるため "Ok"や)は無視されている 正常動作 Case 1e Case 1f

Case 1aと同じ Case 1g

181 https://github.com/stuncloud/UWSCR/issues/181 と同様か、別の現象かも

これは要調査 Case 2a Case 2b Case 2c

いずれもCase 1aと同様 それぞれの代入式で"から文末までである文字列が代入されている Case 3

Case 1aおよび2 と同様 Case 4a Case 4b Case 4c

いずれもthenを省略したif文扱いとなっている condはa = 文字列で、文字列が文末までなので次のトークンがEofとなり、そのためブロック文の閉じトークン(endif)がないというエラーになる 動作的には正常 対策について

  • バグっぽいのはCase 1gのみ
  • 文字列トークンの生成方法については要検討
    • _を伴わない改行があったらInvalidトークンを返すとか?
    • 閉じてない文字列トークンは最初の"や'をInvalid扱いで良さそう
  • 構文エラーをわかりやすくする
    • 関数の閉じカッコがないなら閉じカッコがないというメッセージにする等

確認

@DIYJii https://github.com/DIYJii

以下のCaseにおいてエラーの行番号がスクリプトのどの行を示しているのか教えてください

  • 1a
  • 1c
  • 4b
  • 4c

— Reply to this email directly, view it on GitHub https://github.com/stuncloud/UWSCR/issues/184#issuecomment-2157828046, or unsubscribe https://github.com/notifications/unsubscribe-auth/BH6AXYTLUKQDMTTQ5RSEONTZGVWQ5AVCNFSM6AAAAABJBZBP3OVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCNJXHAZDQMBUGY . You are receiving this because you were mentioned.Message ID: @.***>

stuncloud commented 5 months ago

@DIYJii では存在しない行を指しているといった問題はないと考えて良さそうですかね、座標カウンタにバグがあることを懸念していました

DIYJii commented 5 months ago

そうですね。 只、人間的には、自分が何も書いてない行のことをエラーと言われても?となりますが。 最後の文以降にブランク行が有る事は人間の目ではわかりませんから。Downボタンを押して確認でもしない限り。

On Mon, Jun 10, 2024 at 8:25 PM Joey Takahashi @.***> wrote:

@DIYJii https://github.com/DIYJii では存在しない行を指しているといった問題はないと考えて良さそうですかね、座標カウンタにバグがあることを懸念していました

— Reply to this email directly, view it on GitHub https://github.com/stuncloud/UWSCR/issues/184#issuecomment-2158081441, or unsubscribe https://github.com/notifications/unsubscribe-auth/BH6AXYQWMHKWODPMKHJDGL3ZGWELHAVCNFSM6AAAAABJBZBP3OVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCNJYGA4DCNBUGE . You are receiving this because you were mentioned.Message ID: @.***>

stuncloud commented 5 months ago

閉じ記号なしエラーを新設

エラー位置は開始の記号とし、不明な閉じ記号をエラーメッセージで示す

エラー条件

DIYJii commented 5 months ago

UWSCで同じ事をTestしてみました。全てエラーとなり実行フェーズ迄行ったものは有りません。(1gのUWSCR ユニークは除く)

Case 1a MsgBOX("Ok?)

EXIT 式がおかしい or 型が合っていない 1行目:MSGBOX("Ok?)

Case 1b MsgBOX("Ok?"

EXIT 関数が正しく閉じていません 1行目:MsgBOX("Ok?"

Case 1c MsgBox(Ok?")

EXIT 変数:OK?"が定義されていません 1行目:MsgBox(Ok?")

Case 1d MsgBox"Ok?")

EXIT SyntaxError 1行目:MsgBox"Ok?")

Case 1e ID = FOPEN("C:\Users\Public\Documents\Test.txt, F_READ)

EXIT SyntaxError 1行目:ID = FOPEN("C:\Users\Public\Documents\Test.txt, F_READ)

Case 1f ID = EXEC("C:\Users\Public\Documents\UWSCR.exe Test.uws)

EXIT SyntaxError 1行目:ID = EXEC("C:\Users\Public\Documents\UWSCR.exe Test.uws)

Case 2a hoge = "a MSGBOX(hoge) 式がおかしい or 型が合っていない 1行目:HOGE = "a

Case 2b fuga[1] = "a MSGBOX(fuga[1]) 式がおかしい or 型が合っていない 1行目:FUGA[1] = "a

Case 2c dim hoge[]= "a MSGBOX(hoge[0]) 式がおかしい or 型が合っていない 1行目:DIM HOGE[] = "a

Case 3 a = "Ok1" MSGBOX(a) Print "a MSGBOX(a) b = a 式がおかしい or 型が合っていない 3行目:PRINT "a

Case 4a hoge = "a" If hoge = "a Then MSGBOX(hoge) IFBに対してENDIFが無い 2行目:IF HOGE = "a Then MSGBOX(hoge)

Case 4b hoge = "a" If hoge = "a Then MSGBOX(hoge) EndIf 式がおかしい or 型が合っていない 2行目 IF HOGE = "a Then

Case 4c hoge = "a" If hoge = "a Then MSGBOX(hoge) EndIf EndIf 対応するIFBが無い 5行目:ENDIF

On Mon, Jun 10, 2024 at 8:47 PM DIYJii @.***> wrote:

そうですね。 只、人間的には、自分が何も書いてない行のことをエラーと言われても?となりますが。 最後の文以降にブランク行が有る事は人間の目ではわかりませんから。Downボタンを押して確認でもしない限り。

On Mon, Jun 10, 2024 at 8:25 PM Joey Takahashi @.***> wrote:

@DIYJii https://github.com/DIYJii では存在しない行を指しているといった問題はないと考えて良さそうですかね、座標カウンタにバグがあることを懸念していました

— Reply to this email directly, view it on GitHub https://github.com/stuncloud/UWSCR/issues/184#issuecomment-2158081441, or unsubscribe https://github.com/notifications/unsubscribe-auth/BH6AXYQWMHKWODPMKHJDGL3ZGWELHAVCNFSM6AAAAABJBZBP3OVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCNJYGA4DCNBUGE . You are receiving this because you were mentioned.Message ID: @.***>

stuncloud commented 5 months ago

@DIYJii ちなみになんですが、本件の問題はVSCode等のエディタによる支援があれば

といった異常はUWSCRの構文解析を行わずともエディタ上で視覚化されるので、そういったものも併用することをご検討ください 特にVSCodeにはUWSCR拡張機能を提供していて、これにより解析エラーがエディタ上に波線表示されるようになるなど、とても便利です

理想はあらゆる異常を的確にエラーメッセージでユーザーに伝えられることではありますが、これが (UWSCでもそうであったように) なかなか難しく悩ましい問題です わかりにくいエラーに関しては今後もどんどん指摘していただけると改善の方向も見えてくるので助かります

DIYJii commented 5 months ago

分かりました。VSCode勉強してみます。

On Mon, Jun 10, 2024 at 10:05 PM Joey Takahashi @.***> wrote:

@DIYJii https://github.com/DIYJii ちなみになんですが、本件の問題はVSCode等のエディタによる支援があれば

  • 文末まで文字列扱い
  • 閉じカッコがない

といった異常はUWSCRの構文解析を行わずともエディタ上で視覚化されるので、そういったものも併用することをご検討ください 特にVSCodeにはUWSCR拡張機能を提供していて、これにより解析エラーがエディタ上に波線表示されるようになるなど、とても便利です

理想はあらゆる異常を的確にエラーメッセージでユーザーに伝えられることではありますが、これが (UWSCでもそうであったように) なかなか難しく悩ましい問題です わかりにくいエラーに関しては今後もどんどん指摘していただけると改善の方向も見えてくるので助かります

— Reply to this email directly, view it on GitHub https://github.com/stuncloud/UWSCR/issues/184#issuecomment-2158298231, or unsubscribe https://github.com/notifications/unsubscribe-auth/BH6AXYRNIC3AM44PBHFZAPTZGWQARAVCNFSM6AAAAABJBZBP3OVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCNJYGI4TQMRTGE . You are receiving this because you were mentioned.Message ID: @.***>

DIYJii commented 5 months ago

エラー・メッセージ全般に関して、今の所、私としては、 1.エラーを検知しない 2.異常、又は間違えたエラー表示 を報告のクライテリアとしています。

正直言って、UWSCRではエラー・メッセージやマニュアルも含めて、Javaを勉強したことがある人には通じるであろう専門用語が多く出現し、私自身、ネット検索することも有ります。しかし、それについては、あなたの想定するUWSCRユーザーが、どの位のレベルかにより変わりますので、今のところ報告はしていません。

もし、ユーザー層を広げたい等の理由でユーザーの声を聴きたいのなら、例えば、「Ease Of Use」 といった新たなIssue項目を設けるのも、一つの手段かなと思います。ユーザーは気楽につぶやくだけで、返事をする-しない、または、採用-不採用は、あくまでそちらの判断で、というルールも有りかなと思います。何しろフリー・ソフトなのですから。

stuncloud commented 18 hours ago

閉じていない文字列リテラル表記

文字列リテラルについては対応した

対策

リテラル文字列開始文字("または')があった場合は文字列リテラルトークンの解析を行うが、対となる終了文字("または')がない場合はエラー箇所を開始文字の位置とし、エラーメッセージは文字列表記が閉じられていないという内容を出力するようにした

print "12345
print '345

出力

UWSCR構文エラー
test.uws[1, 7] - 文字列表記が開始されていますが、対となる " で閉じられていません
test.uws[2, 7] - 文字列表記が開始されていますが、対となる ' で閉じられていません

変更

print "12345_
67890" // 1234567890

文字列リテラルの改行表記につい_ 以降にコメントが記述できるような実装になっていたが、UWSCではコメントの記述ができないようなのでこれを廃止した

print "12345_  // コメント書くのはNG
67890"

この場合は「12345_ // コメント書くのはNG」という文字列の後に閉じるための"がないため解析エラーとなる