プチコン4 まとめWiki

PXIILIB-0.3.1 パーサコンビネータライブラリ

パンくずリスト

+  目次

2020年3月20日投稿 / 2020年3月26日更新 / 投稿者 : うつりきまぐれ / タグ : 投稿プログラム ツール ライブラリ うつりきまぐれ 構文解析 パーサ パーサコンビネータ オブジェクト JSON

これは何?

プチコン4上で文法を定義して構文解析するためのライブラリです。構文解析とはプログラムを先頭から読んで単語ごとに切り分け、それらを項や式、文、ブロックといったまとまりごとに構造的なデータ (構文木) に整理します。( 厳密には最初の単語ごとの分解処理は「字句解析」という構文解析の前の別のステップです。) 構文解析については説明が難しいのでまあググってもらえると助かります。

このライブラリが追加で使用するオブジェクトライブラリと JSON 解析・生成ライブラリ、および actorbug さんが製作した 正規表現ライブラリ の移植版がひとつのファイルになっています。

このライブラリでは文法を定義するのにパーサコンビネータというものを使います。詳しい説明はググれカス このライブラリを使おうと思っている皆さんは知っているだろうという前提で進めます。

サンプルプログラムとして四則演算と括弧が利用できる計算機を用意しています。また、ライブラリ内にもパーサコンビネータを実際に利用した JSON 解析ライブラリを内蔵しています ( 逆に生成もできます ) 。

ライブラリの使用

ライブラリを読み込む

構文解析ライブラリおよびオブジェクトライブラリの本体は PXII.LIB という名前です。以下のようにしてライブラリを読み込み、実行します。

  1. EXEC ”PXII.LIB”,1

別のプロジェクトから参照するときは EXEC がエラーになるので、代わりに LOAD でスロットに読み込んでから EXEC で実行してください。

  1. LOAD ”PXIILIB−0.3.0/PXII.LIB”,1
  2. EXEC 1

ライブラリの初期化のための DEFGOSUB の呼び出しは特に必要ありません。

文法を定義する

構文解析を行うより先に、次のように文法を定義してください。これは整数の四則演算の例です。符号はありません。……なお、実際に計算を行うには ACTP を使ってアクションというコールバック DEF も指定しなければならないため、これよりも少々複雑になります。

  1. PXDEFPC @_SPACE,REGEXP(”\s*”)
  2. PXDEFPC @EXPR,LISTP(@TERM,CHARP(”+−”))
  3. PXDEFPC @TERM,LISTP(@TERM,CHARP(”*/”))
  4. PXDEFPC @FACT,ORP(@REAL,SEQP(”(”,@EXPR,”)”))
  5. PXDEFPC @REAL,REGEXP(”[0−9]+”)

用意されているパーサを組み合わせて、新たなパーサを作成します。パーサは通常の変数に代入して利用できますが、これでは上記のような再帰文法が定義できません。( Undefined variable となる) そのため、別の手段として PXDEFPC を用いて @ からはじまる名前をつけます。この名前は上記の @EXPR のように再帰できます。( ただし自身の名前が含まれる再定義は現在のところできません ) またパーサコンビネータの実体はオブジェクトですが、代わりに名前を指定できるようになります。ただし @_SPACE という名前は、スキップパーサを示すために予約されており、ここに指定したものは PXPARSE が呼び出されるたびにパースされ無視されます。

また、@ から始まらない文字列を直接指定した場合は、自動的に TEXTP に変換されます。つまり、@ から始まらない文字列を読み取る場合は TEXTP を省略できます。

用意されているすべてのパーサコンビネータの詳細は パーサコンビネータのリファレンス を参照してください。

構文解析を行う

実際に構文解析を行うには次のようにします。

  1. DIM SOURCE=”11+(9−5)*7”
  2. DIM RES=PXPARSE(SOURCE,0,@EXPR)

第1引数に入力、第2引数に開始位置、第3引数にパーサコンビネータを指定します。結果はオブジェクトでまとめて返るため、情報を取得するには OBJGET などでキーから値を得る必要があります。オブジェクトの使い方については オブジェクトを扱う を参照してください。

次のようにして、パースが成功したかどうかと次回の開始位置 ( 終端位置 + 1 ) および読み取った文字列を取得できます。パースが失敗した場合は、その時点での位置になります。

  1. DIM SUCCESS=OBJGET(RES,”SUCCESS”)
  2. DIM EPOS=OBJGET(RES,”POS”)
  3. DIM BUFF=OBJGET(RES,”BUFF”)

また SEQPREPP など一部のパーサコンビネータは別のパーサコンビネータを引数にとるため、これらの結果を参照できるように、”SUCCESS””POS” および ”BUFF” のほかにも追加の情報が入っています。たとえば SEQP では、”SEQ0” に最初に指定したパーサコンビネータの結果が入ります。これもまたひとつの結果オブジェクトなので ”POS” などのキーを持っています。

パーサを拡張する ( v0.3.1 から )

PXDEFPC で定義した名前は再定義できるので、このライブラリを用いて言語処理系などを作ると、外部からパーサを変更することができます。たいていは後に出る例のように、そのパーサ自身を含むように拡張することになります。

しかし、その場合には問題があります。たとえば @FACT という名前のパーサがあったとします。先ほどの計算機で変数も利用できるように、次のように @FACT を使って @FACT を再定義すると、パース時に Stack overflow エラーになることがあります。( 以下の例で @VAR は既に定義されているものとします )

  1. PXDEFPC @FACT,ORP(@FACT,@VAR)

これを回避するには、再定義する対象のパーサを EXTP で包みます。

  1. PXDEFPC @FACT,ORP(EXTP(@FACT),@VAR)

バージョン v0.3.1 以上で利用できます。

オブジェクトを扱う

この構文解析ライブラリでは、パーサコンビネータを保存したりパースの結果を返すのにオブジェクトが使われます。このオブジェクトは JavaScript のオブジェクトと同じようなものです。オブジェクトの実体は文字列配列ですが、値にキーという名前 ( 文字列の添え字のようなものです ) を付けて、あとからその名前で取得できるようになります。

オブジェクトには次の種類の値を格納することができます。

  • デフォルト値
  • 整数
  • 実数
  • 文字列
  • 別のオブジェクト

オブジェクトライブラリを使った例です。

  1. ’ オブジェクトを生成
  2. VAR A=OBJECT()
  3. ’ 数値や文字列を入れる
  4. OBJSET A,”SCORE”,80
  5. OBJSET B,”COMMENT”,”おめでとう”
  6. ’ 内容を表示
  7. ? ”あなたの点数は”;OBJGET(A,”SCORE”)
  8. ’ 別のオブジェクトを生成
  9. VAR B=OBJECT()
  10. ’ 同じように数値や文字列を入れる
  11. OBJSET B,”NAME”,”山田”
  12. OBJSET B,”AGE”,22
  13. ’ オブジェクトに別のオブジェクトを格納
  14. OBJSET B,”RESULT”,A
  15. ’ ピリオドで階層を指定
  16. ? OBJGET(B,”RESULT.COMMENT”);”!”
  17. ’ こうすることもできる (こちらの方は遅い)
  18. ? OBJGET(OBJGET(B,”RESULT”),”COMMENT”);”!”
  19. ’ OBJSET にもピリオドを使える
  20. OBJSET B,”RESULT.SCORE”,0

オブジェクトのキーを CHR$(&HFFFF) から始めることはできません。CHR$(&HFFFF) というキーはオブジェクトの終端を表すのに使用されています。

あらかじめ文字列配列内でのインデックスが予測できる場合は OBJGETH などを利用し、ヒントとしてインデックスを与えて高速化する方法もあります。

構文解析のリファレンス

パーサコンビネータを定義したり実際に構文解析を行うための DEF です。

PXDEFPC …… パーサに名前を付ける

  1. DEF PXDEFPC PCDEF,PC
引数
  • PCDEF : 新しいパーサコンビネータの @ から始まる名前
  • PC : パーサコンビネータ ( オブジェクトか @ で始まる名前 )

新しいパーサコンビネータを名前を付けて定義します。変数に格納することとの違いは、定義前に利用できるため再帰的な文法が定義できることです。

スキップパーサを指定するには @_SPACE という名前で定義します。スキップパーサはかならず成功する必要があります。

PXPARSE …… 構文解析を実行する

  1. DEF PXPARSE SOURCE,SPOS,PC OUT RES
引数
  • SOURCE : ソースとなる文字列
  • SPOS : 開始位置 ( 通常は 0 )
  • PC : パーサコンビネータ ( オブジェクトか @ で始まる名前 )
戻り値
  • RES : 結果オブジェクト
    • ”POS” : 終端位置 + 1
    • ”BUFF” : 読み取った文字列

構文解析を実行します。結果はオブジェクトで返ってきます。

PXGETPCOBJ …… パーサの名前からパーサオブジェクトを取得

  1. DEF PXPARSE PC OUT PCOBJ
引数
  • PC : パーサコンビネータ ( オブジェクトか @ で始まる名前 )
戻り値
  • PCOBJ : パーサオブジェクト

PXDEFPC で定義したパーサの名前から、その実体を取得します。未定義の場合はエラーとなります。

パーサコンビネータのリファレンス

PX.LIB に用意されているパーサコンビネータです。

BASEP …… 基底パーサ

  1. DEF BASEP()

何も読み取らないパーサを作成します。パースは常に成功します。

ACTP …… アクションつきパーサ

  1. DEF ACTP(SUBPC,ACALL)
引数
  • SUBPC : パーサ
  • ACALL : DEF の名前

別のあるパーサを引数にとり、その読み取りが成功したときにアクションというコールバック DEF を呼び出すパーサを返します。アクションには引数として結果オブジェクトが渡されます。このオブジェクトは改変することができるので、”BUFF” ( 読み取った文字列 ) を加工したり、追加の情報を設定することもできます。実際に同梱されている計算機のサンプル ( 簡易版のプログラムが こちら にあります ) では ”VALUE” という名前で計算結果を格納しています。

COMMON でない DEF を指定する際は 0: のように、スロットプレフィックスを加える必要があります。

EXTP …… 展開パーサ

  1. DEF EXTP(SUBPC)
引数
  • SUBPC : パーサ

別のあるパーサを引数にとり、そのパーサを展開したものを返します。その展開とは、名前で指定したパーサを取得することです。すでにパーサの実体である場合はそのまま返されます。やっていることは PXGETPCOBJ と完全に同じです。

これが有用なのはパーサを拡張するときです。こちら をご覧ください。

TEXTP …… 文字列パーサ

  1. DEF TEXTP(TEXT)
引数
  • TEXT : 読み取る文字列

固定の文字列を読み取るパーサを作成します。文字列が @ から始まる場合を除いて、TEXTP は省略できます。つまり、パーサコンビネータに文字列を直接指定することができ、自動的に TEXTP に変換されます。

CHARP …… 文字パーサ

  1. DEF CHARP([CHARS])
引数
  • CHARS (省略可) : 想定する文字を並べた文字列。

現在位置の1文字が指定された文字列に含まれる場合、その1文字を読み取るパーサを作成します。空文字列にしたり、引数そのものを省略した場合は、どんな場合でも 1 文字読み取ります ( ただし既に EOF である場合は失敗します ) 。

REGEXP …… 正規表現パーサ

  1. DEF REGEXP(REGEX[,FLAGS])
引数
  • REGEX : 正規表現の文字列。
  • FLAGS (省略可) : フラグ。省略時は 0

正規表現にマッチする文字列を読み取るパーサを作成します。第1引数には文字列で直接指定します。REGEX で生成した正規表現オブジェクトを指定するわけではありません。またオプションで大文字小文字を区別しないといったフラグを指定できます。

actorbug さんの 正規表現ライブラリ を移植して使用しています。

利用できる正規表現の一覧

こちら よりそのまま引用しています。

メタ文字説明
\直後のメタ文字を無効化して通常文字として扱う
\nLF、CHR$(10)
\rCR、CHR$(13)
\tTab、CHR$(9)
\xFF16進2桁で文字コード指定
\uFFFF16進4桁で文字コード指定
[]文字クラス、括弧内の文字のいずれかにマッチ、-で範囲指定可能
[^]否定文字クラス、括弧内の文字以外にマッチ、-で範囲指定可能
.任意の1文字(改行を除く)にマッチ、単一行モードなら改行もマッチ
\d数字、[0-9]と同じ
\D非数字、[^0-9]と同じ
\w単語構成文字、[a-zA-Z0-9_]と同じ
\W非単語文字、[^a-zA-Z0-9_]と同じ
\s空白文字、[ \n\r\t]と同じ
\S非空白文字、[^ \n\r\t]と同じ
^文字列の先頭、複数行モードなら改行の次にもマッチ
$文字列の末尾 or 最後が改行ならその前、複数行モードなら改行の前にもマッチ
\A文字列の先頭
\Z文字列の末尾 or 最後が改行ならその前
\z文字列の末尾
\b単語境界
\B単語境界以外
\1~\9後方参照
()グループ化 & キャプチャ
(?:)グループ化(キャプチャなし)
(?=)肯定の先読み
(?!)否定の先読み
(?<=)肯定の戻り読み(通常文字・文字クラス・一部アンカーのみ使用可)
(?<!)否定の戻り読み(通常文字・文字クラス・一部アンカーのみ使用可)
(?>)アトミックなグループ
(?修飾子)モード修飾子(?i)(?-i)など
(?修飾子:)モード修飾子の範囲(?i:...)など
|選択
*直前の式の0回以上の繰り返し、{0,}と同じ
+直前の式の1回以上の繰り返し、{1,}と同じ
?直前の式が0回か1回現れる、{0,1}と同じ
{n}直前の式のn回の繰り返し
{m,}直前の式のm回以上の繰り返し
{m,n}直前の式のm回以上n回以下の繰り返し
*?直前の式の0回以上の繰り返し(最短マッチ)
+?直前の式の1回以上の繰り返し(最短マッチ)
??直前の式が0回か1回現れる(最短マッチ)
{m,}?直前の式のm回以上の繰り返し(最短マッチ)
{m,n}?直前の式のm回以上n回以下の繰り返し(最短マッチ)
*+直前の式の0回以上の繰り返し(強欲)
++直前の式の1回以上の繰り返し(強欲)
?+直前の式が0回か1回現れる(強欲)
{m,}+直前の式のm回以上の繰り返し(強欲)
{m,n}+直前の式のm回以上n回以下の繰り返し(強欲)
フラグ一覧

こちら よりそのまま引用しています。

オプションは数値で指定してください。複数指定する場合は足します。

オプション説明
RXOPT_IC1大文字小文字を区別しない
RXOPT_SL2単一行モード("."が改行にもマッチする)
RXOPT_ML4複数行モード("^","$"が改行前後にもマッチする)

OPTP …… 省略可能パーサ

  1. DEF OPTP(SUBPC)
引数
  • SUBPC : パーサ

別のあるパーサを引数にとり、読み取りに失敗しても位置を戻して成功と扱うパーサを作成します。

失敗することがないので省略可能な部分を定義するのに利用します。

AHEADP …… 肯定先読みパーサ

  1. DEF AHEADP(SUBPC)
引数
  • SUBPC : パーサ

別のあるパーサを引数にとり、読み取ったあとに位置を戻すパーサを作成します。読み取れなかった場合は失敗します。

NOTP …… 否定先読みパーサ

  1. DEF NOTP(SUBPC)
引数
  • SUBPC : パーサ

別のあるパーサを引数にとり、読み取れた場合は逆に失敗し、読み取れなかった場合にその位置で成功するパーサを作成します。

特定の識別子を読み取り、直後にアルファベットや数字などの、識別子を構成する文字が続いていないかどうかを確認できます。

ORP …… 選択パーサ

  1. DEF ORP(...)
引数
  • ... : 1個以上のパーサ

別の複数のパーサを引数にとり、それらを順番にパースしていき、どれかが成功すればその結果をこのパーサの結果とするパーサを返します。

最初に成功したパーサの結果オブジェクトが、このパーサの結果オブジェクトとなります。どれかが成功した後は、それ以降のパーサは実行されません。

SEQP …… シーケンスパーサ

  1. DEF SEQP(...)
引数
  • ... : 1個以上のパーサ
追加の結果オブジェクトのキー
  • ”SEQ#” : 結果の数。SEQP に渡した引数の数と一致します。
  • ”SEQ0” : シーケンスの 0 番目の (最初の) パーサの結果。同様に 1 番目以降も指定できます。”SEQ0.BUFF” のようにすれば、シーケンスの最初のパーサが読み取った文字列を取得できます。

別の複数のパーサを引数にとり、それらを順番にパースしていき、最後まで成功した場合をこのパーサが成功したと扱うパーサを返します。

それぞれのパーサの結果オブジェクトが、このパーサの結果オブジェクトに格納されます。それらすべてを後から参照することが可能となります。

REPP …… 繰り返しパーサ

  1. DEF REPP(SUBPC,MINC,MAXC)

別のあるパーサを引数にとり、指定した回数の範囲、繰り返されるパーサを返します。ただし、正規表現が使える場合は、REGEXP の方が高速です。

引数
  • SUBPC : パーサ
  • MINC : 最小回数。制限を設けない場合は 0 を指定。
  • MAXC : 最大回数。制限を設けない場合は 0 を指定。
追加の結果オブジェクトのキー
  • ”REP#” : 結果の数。繰り返し読み取った回数です。
  • ”REP0” : 最初に読み取った結果。同様に 1 番目以降も指定できます。”REP0.BUFF” のようにすれば、1 回目にパーサが読み取った文字列を取得できます。

それぞれの回の結果オブジェクトが、このパーサの結果オブジェクトに格納されます。それらすべてを後から参照することが可能となります。

LISTP …… リストパーサ

  1. DEF LISTP(SUBPC,DELPC)
引数
  • SUBPC : 項目を読み取るパーサ
  • DELPC : 区切りを読み取るパーサ
追加の結果オブジェクトのキー
  • ”LIST#” : 項目の数。項目は (項目数 - 1) 番目、デリミタは (項目数 - 2) 番目まで有効です。
  • ”LISTSUB0” : 0 番目の項目の結果オブジェクト。1 番目以降も指定できます。
  • ”LISTDEL0” : 0 番目の項目の結果オブジェクト。1 番目以降も指定できます。

項目用のパーサとデリミタ ( 区切り ) 用のパーサを引数にとり、デリミタで区切られたリストを読み取るパーサを返します。

それぞれの項目の結果オブジェクトが、このパーサの結果オブジェクトに格納されます。

オブジェクトのリファレンス

階層化可能なオブジェクトを実現するための DEF 。JSON を扱うこともできます。

OBJECT …… 空のオブジェクトを生成

  1. DEF OBJECT OUT OBJ
戻り値
  • OBJ : 空のオブジェクト

新しい空のオブジェクトを生成します。やっていることは ARRAY$(0) と同じです。

OBJGET …… オブジェクトから値を取得

  1. DEF OBJGET OBJ,PATH OUT VALUE
引数
  • OBJ : オブジェクト
  • PATH : 取得するためのキー。ピリオドで階層を指定できます。
戻り値
  • VALUE : 取得した値

オブジェクトから、キーを指定して値を取得します。

値は数値や文字列のようにプリミティブな型である場合も、オブジェクトである場合もあります。取得したオブジェクトからさらに値を取得したい場合、OBJGET で取得したオブジェクトに対してさらに OBJGET を使うより、ピリオドに続けて一気に指定した方が高速です。

  1. ’ 上よりも下のほうが速い
  2. OBJGET(OBJGET(OBJ,”FOO”),”BAR”)
  3. OBJGET(OBJ,”FOO.BAR”)

なおキーが存在しない場合はデフォルト値が返ってきます。TYPEOF で判定することができますが、存在を確認するだけならば OBJHAS という関数もあります。

OBJSET …… オブジェクトに値を設定

  1. DEF OBJSET OBJ,PATH,VALUE
引数
  • OBJ : オブジェクト
  • PATH : 設定するためのキー。ピリオドで階層を指定できます。
  • VALUE : 設定する値

オブジェクトに、キーを指定して値を設定します。OBJGET と同じくピリオドを使って階層を指定できます。キーが存在しなければ追加され、存在すれば上書きされます。

OBJHAS …… オブジェクトにキーが存在するか確認

  1. DEF OBJHAS OBJ,PATH OUT HAS
引数
  • OBJ : オブジェクト
  • PATH : 存在を確認するキー。ピリオドで階層を指定できます。
戻り値
  • HAS : キーが存在するかどうか

オブジェクトに、指定したキーがあるかどうかを確認します。存在すれば #TRUE しなければ #FALSE が返ります。

オブジェクトにあるキーの一覧を取得するには OBJPATHS を使います。

OBJDEL …… オブジェクトからキーを削除

  1. DEF OBJDEL OBJ,PATH
引数
  • OBJ : オブジェクト
  • PATH : 削除するキー。ピリオドで階層を指定できます。

オブジェクトから、キーを削除します。そのキーの値がオブジェクトだった場合はオブジェクトごと削除されます。キーが存在しない場合は何も起こりません。

OBJPATHS …… オブジェクトからキーを削除

  1. DEF OBJPATHS OBJ,SUB OUT PATHS
引数
  • OBJ : オブジェクト
  • SUB : 子オブジェクト以下のキーも取得するかどうか
戻り値
  • PATHS : キーの一覧

オブジェクトのキーの一覧を文字列配列で取得します。第2引数に #FALSE を指定したときは直下のキーのみを取得しますが、#TRUE を指定したときはキーの値がオブジェクトだった場合に再帰的にそのオブジェクトのキーの一覧も加えます。このキーの一覧はソートされています。

OBJGETH …… オブジェクトからインデックスヒントつきで値を取得

  1. DEF OBJGETH OBJ,INDEX,PATH OUT VALUE
引数
  • OBJ : オブジェクト
  • INDEX : キーがある可能性が高いインデックス。
  • PATH : 取得するためのキー。ピリオドで階層を指定できます。
戻り値
  • VALUE : 取得した値

オブジェクトから、キーを指定して値を取得します。

OBJGET と違うのは、インデックスという追加の引数を指定するという点です。インデックスとはオブジェクトの実体である文字列配列における添え字のことです。オブジェクトに入るキーが初めから決まっている、あるいはそうでなくてもキーのあるインデックスが固定値または計算で予測できる場合はヒントとしてそのインデックスを渡すことで、インデックスで指定した位置がまさにそのキーであった場合にはキーを検索せずそのままその位置を参照するため、高速になります。インデックスが異なった場合、つまり指定したインデックスにキーがなかった場合は OBJGET と同様にキーを検索します。

OBJGETH では数値と文字列のみを取得できます。子オブジェクトには対応していません。

OBJSETH …… オブジェクトにインデックスヒントつきで値を設定

  1. DEF OBJSETH OBJ,INDEX,PATH,VALUE
引数
  • OBJ : オブジェクト
  • INDEX : キーがある可能性が高いインデックス。
  • PATH : 設定するためのキー。ピリオドで階層を指定できます。
  • VALUE : 設定する値

オブジェクトに、キーを指定して値を設定します。OBJGET と同じくピリオドを使って階層を指定できます。キーが存在しなければ追加され、存在すれば上書きされます。

OBJSET と違う点は OBJGETH にある説明と同じく、キーのある可能性が高い位置を同時に指定して、その位置が指定したキーだった場合にその位置を直接参照することです。

OBJSETH では数値と文字列のみを設定できます。子オブジェクトには対応していません。

ISOBJECT …… オブジェクトかどうかを判定

  1. DEF ISOBJECT VALUE OUT ISOBJECT
引数
  • VALUE : 判定する値
戻り値
  • ISOBJECT : オブジェクトかどうか

渡された値がオブジェクトかどうかを調べます。やっていることは TYPEOF(VALUE)==#T_STRARRAY と同じです。

OBJFIND …… オブジェクトのキーを検索 (internal)

  1. DEF OBJFIND OBJ,PATH,SINDEX,EINDEX OUT INDEX
引数
  • OBJ : オブジェクト
  • PATH : 検索するキー。ピリオドで階層を指定できます。
  • SINDEX : 検索する先頭位置 - 1 。オブジェクトの先頭から検索する場合は -1 です。
  • EINDEX : 検索する末尾位置 + 1 。オブジェクトの末尾まで検索する場合は LEN(OBJ) です。
戻り値
  • INDEX : キーのあるオブジェクト上のインデックス

オブジェクトのキーのあるべき位置を取得します。キーがない場合はキーを追加 ( INSERT ) する場合の位置となります。キーの値がオブジェクトだった場合は先頭の位置を返します ( そのオブジェクトの先頭のキーはその次の位置にあります )。終端位置は同じキーで OBJFINDEND を使用します。

通常使用ではあまり推奨していません。

OBJFINDEND …… オブジェクトのキーを検索 (internal)

  1. DEF OBJFINDEND OBJ,PATH,SINDEX,EINDEX OUT INDEX
引数
  • OBJ : オブジェクト
  • PATH : 検索するキー。ピリオドで階層を指定できます。
  • SINDEX : 検索する先頭位置 - 1 。通常は OBJFIND の戻り値を使用します。
  • EINDEX : 検索する末尾位置 + 1 。オブジェクトの末尾まで検索する場合は LEN(OBJ) です。
戻り値
  • INDEX : キーのあるオブジェクト上のインデックス

キーの値がオブジェクトの場合、終端位置を取得するのに使われます。OBJFIND(OBJ,PATH+”.”+CHR$(&amp;HFFFF),SINDEX,EINDEX) と同じです。

通常使用ではあまり推奨していません。

JSON2OBJ …… JSON から オブジェクトを生成

  1. DEF JSON2OBJ JSON OUT VALUE
引数
  • JSON : JSON 文字列
戻り値
  • VALUE : 生成されたオブジェクトまたはプリミティブ値

JSON をもとに新しいオブジェクトを生成します。SmileBASIC の文字列リテラルに直接 JSON を記述することも踏まえて文字列リテラルを ではなく ' で括ることもできるように拡張されています。エスケープシーケンスも有効です。

OBJ2JSON …… オブジェクトから JSON を生成

  1. DEF OBJ2JSON VALUE OUT JSON
引数
  • VALUE : オブジェクトまたはプリミティブ値
戻り値
  • JSON : 生成された JSON 文字列

オブジェクトまたは単独の数値、文字列から JSON を生成します。生成される JSON にはスペースやインデントは含まれません。

サンプル

計算機

テキトーに作ったものです

  1. OPTION STRICT
  2. ACLS
  3. LOAD ”PXIILIB−0.3.0/PXII.LIB”,1
  4. EXEC 1
  5. INITPC
  6. LOOP
  7.  LINPUT ”?”;EXPR
  8.  PRINT ”=”;EVAL(EXPR)
  9. ENDLOOP
  10. DEF INITPC
  11.  PXDEFPC @_SPACE,REGEXP(”[\x20]*”)
  12.  PXDEFPC @EXPR,ACTP(LISTP(@TERM,CHARP(”+−”)),”0:ONCALCB”)
  13.  PXDEFPC @TERM,ACTP(LISTP(@FACT,CHARP(”*/%”)),”0:ONCALCB”)
  14.  PXDEFPC @FACT,ACTP(SEQP(REGEXP(”[−]*”),ORP(@REAL,SEQP(”(”,@EXPR,”)”))),”0:ONFACT”)
  15.  PXDEFPC @REAL,REGEXP(”([0−9]+(\.[0−9]*)?|[0−9]*\.[0−9]+)”)
  16. END
  17. DEF EVAL(EXPR)
  18.  DIM RES=PXPARSE(EXPR,0,@EXPR)
  19.  IF OBJGET(RES,”SUCCESS”) THEN
  20.   RETURN OBJGET(RES,”VALUE”)
  21.  ELSE
  22.   RETURN POW(2,1024)*0 ’nan
  23.  ENDIF
  24. END
  25. DEF ONFACT RES
  26.  DIM SIGN=1−(LEN(OBJGET(RES,”SEQ0.BUFF”)) MOD 2)*2
  27.  DIM BUFF=OBJGET(RES,”SEQ1.BUFF”)
  28.  IF LEFT$(BUFF,1)==”(” THEN
  29.   OBJSET RES,”VALUE”,SIGN*OBJGET(RES,”SEQ1.SEQ1.VALUE”)
  30.  ELSE
  31.   OBJSET RES,”VALUE”,SIGN*VAL(BUFF)
  32.  ENDIF
  33. END
  34. DEF ONCALCB RES
  35.  DIM I,O,A,B
  36.  A=OBJGET(RES,”LISTSUB0.VALUE”)
  37.  FOR I=1 TO OBJGET(RES,”LIST#”)−1
  38.   O=OBJGET(RES,”LISTDEL”+STR$(I−1)+”.BUFF”)
  39.   B=OBJGET(RES,”LISTSUB”+STR$(I)+”.VALUE”)
  40.   A=CALCB(O,A,B)
  41.  NEXT
  42.  OBJSET RES,”VALUE”,A
  43. END
  44. DEF CALCB(O,A,B)
  45.  CASE O
  46.   WHEN ”+”:RETURN A+B
  47.   WHEN ”−”:RETURN A−B
  48.   WHEN ”*”:RETURN A*B
  49.   WHEN ”/”:RETURN A/B
  50.   WHEN ”%”:RETURN A MOD B
  51.  ENDCASE
  52. END

公開キー

プチコン4用の公開キーです。

プチコン4 公開キー
4RK33W34V

更新履歴

v0.3.1 ( 2020/03/26 )

  • パーサを展開するための EXTP を追加。パーサを再定義する際に使用できます。詳しい解説は パーサを拡張する を参照。

v0.3.0 ( 2020/03/23 )

  • 初版。

コメント

PXIILIB に関する感想や意見・要望ならなんでもどうぞ。バグ報告もこちらでお願いします。


メニュー 【4】

過去シリーズWiki

ヘルプ

リンク

最近の更新

最近の人気ページ

オンライン情報

  • 現在同時に 1 人がこのサイトを見ています
  • このページはこれまでに 1049 回、本日は 1 回、昨日は 0 回閲覧されました

ページの先頭に戻る

表示モード : [ スマホ・3DS対応表示 | クラシック表示 ]
PukiWiki 1.4.7 Copyright © 2001-2006 PukiWiki Developers Team. License is GPL. Based on "PukiWiki" 1.3 by yu-ji
ページの処理時間 : 0.276 秒 | このページの最終更新 : 2022/09/20 (火) 12:23:39 (565d) | ログイン
Copyright(C) 2011-2019 プチコンまとめWiki