PEG.jsの文法で、POSIXの基本的な正規表現の範囲式のようなものを使用できると便利です。 例えば:
"a"\{1,7\}
a
、 aa
、...、 aaaaaaa
に一致します
"a"\{0,1\}
空の文字列とa
に一致します
"a"\{,6\}
最大6つのa
を持つ文字列に一致します
"a"\{6,\}
6つ以上のa
の文字列に一致します
"a"\{3\}
aaa
にのみ一致し、 "a"\{3,3\}
と同等です
この機能は実装しません。
主な理由は、PEG.jsの文法に{m,n}
構文の余地がないことです。中括弧はすでにアクションに使用されており、あなたが提案するようにバックスラッシュを使用したくありません(醜くて互換性がありません)現在最も使用されているPerlregexpsと、他のPEG.js構文のソース)または他の区切り文字(混乱を招く可能性があります)を使用します。
私の経験では、この種の制限された繰り返しは、主に文法の「字句」部分( color = "#" hexdigit hexdigit hexdigit hexdigit hexdigit hexdigit
などの規則)で発生しますが、それほど頻繁ではありません。 式のシーケンスと既存の繰り返し演算子( *
、 +
、 ?
)を使用するだけで問題ないと思います。
私は再考し、この問題を再開します。 ユーザーは、任意の繰り返し回数を指定できることを強く望んでいるようです。
{
と}
はすでにアクションに使用されており、それらを再利用するとあいまいさが生じるため、正規表現のような{m,n}
構文は避けたいと思います。 私は現在このようなことを考えています:
"foo" @ 1..10 // repeat 1 to 10 times
"foo" @ 1.. // repeat at least once
"foo" @ ..10 // repeat at most 10 times
最大の問題は、区切り文字がどうあるべきか、そして範囲をマークアップする方法です。
区切り文字に関しては、 @
は私にはいいようです。 %
と#
を検討していましたが、最初の1つはすでに文字列補間(Pythonなど)に関連付けられており、2つ目はコメント(さまざまな言語)に関連付けられています。 セパレータを完全にスキップすることも考えています。
"foo" 1..10 // repeat 1 to 10 times
"foo" 1.. // repeat at least once
"foo" ..10 // repeat at most 10 times
範囲のマークアップについては、Rubyからインスピレーションを得ました。 -
についても考えていましたが、マイナス記号のように見えます。 一方、Pythonのような:
も私には似合います。
ハーフオープンレンジについてはよくわかりません。 たぶん、次のように+
と-
を使用してそれらをマークアップする方が良いでしょう:
"foo" @ 1+ // repeat at least once
"foo" @ 10- // repeat at most 10 times
アイデアやコメントはありますか?
この機能をサポートする予定があるのは本当に素晴らしいです!
私はあなたの(デフォルトの)提案が好きです:
"foo" @ 1..10 // 1〜10回繰り返す
"foo" @ 1..//少なくとも1回繰り返す
"foo" @..10//最大10回繰り返す
ハーフオープン範囲の+/-構文は好きではありません。ダブルドット構文は、はるかに直感的で読みやすいIMOです。
IMOの「#」は当然数値/カウントを意味し、「@」は自然に参照を意味するため、「#」と「@」を使用することだけを考え直しました。したがって、「#」はもう少し直感的で読みやすいかもしれません。 (そしておそらくあなたは何かのために将来「@」を使うことができるでしょうか?) しかし、これは実際には小さな問題であり、「@」構文に満足しています。
乾杯!
簡単なコメント: @
と%
は#
よりも良い選択だと思います。なぜなら、PEG.js文法をサポートしない構文ハイライター、特に推測しようとするものはそうだからです。構文(Stack Overflowのコードハイライターなど)は、 #
をコメントの先頭として解釈する可能性が高く、その時点からEOLまで「コメントの色」で表示されます。 もちろん、これは論理や推論に基づく選好ではなく、実用主義に基づく選好です。
{num, num}
の特別な場合はどうですか? { , num}
と{ num, }
は有効なjsコードではなく、 {num, num}
と{ num }
は無意味なので、これは繰り返しを意味します。
アクションが他の言語のものであっても、それらは意味をなさない可能性があります。
私は提案されたものの中でこれらの変種が好きです(しかし、あなたが作者なので、これはもちろんあなた次第です:)):
// why we need separator, anyway? for me it looks very cool and simple to understand
"foo" 1..10 // repeat 1 to 10 times
"foo" 1.. // repeat at least once
"foo" ..10 // repeat at most 10 times
また
"foo"@1..10 // repeat 1 to 10 times
"foo"@1.. // repeat at least once
"foo"@..10 // repeat at most 10 times
しかし、2番目はあまり好ましくありません
..
のおかげで一貫した演算子のように見えるので、 x..y
/ ..y
/ x..
のアイデアは非常にクールに見えます。
+/-
は、混乱して..
の上の追加の演算子になるため、私にとっては問題ありません( +
はすでに使用されています)
もう一度考えてみてください。 これらは機能しますか?
'foo'<1,5>
'foo'< ,3>
'foo'<2, >
<
と>
は現在、文法で使用されていないため
:+1:私からは、よさそうだ。
もちろん、 <,3>
は<0,3>
$と同等なので、最小数だけが必要な場合もあります。 これは、ECMAがJavaScriptの正規表現に対して行ったことと一致します。
私は<,>
が好きです。 ただし、 <3>
を<3,3>
と同じように使用することもお勧めします。
私は同意します<>
構文は、可能な限りRegExpの{}
の動作に直接マップする必要があります。
私が間違っていなければ、範囲内の変数名を許可する場合を除いて、区切り文字を追加する必要はありません。
foo 1,2 fighter
bar ,3 tender
baz 4, lurhmann
qux 5 quux
すべて明確です。
@pygy 、区切り文字を使用しない場合の問題は、言語の構文の進化を妨げる可能性があることです。
たとえば、後で何か他のものにコンマを使用したい場合、構文の衝突が至る所で発生する問題が発生します。 <>
括弧内に制限すると、コンマと数字の表面積が大幅に減少します。
さらに、人々はとにかく正規表現で{1,6}
スタイルを使用することに慣れています。
構文についてはあまり感じませんが、この機能が必要です。式を範囲値として使用できれば素晴らしいと思います。
私の使用例:IMAPサーバー応答のリテラルの解析。これは{42}\r\n...
のようになります。ここで、 42
は、文字列を表す改行の後の文字数です(ここでは省略記号で示されています)。 IMAPリテラルには終了区切り文字がないため、この応答を解析する唯一の方法は文字カウントです。
制限の変数はどうですか? これは、長さを含むヘッダー付きのメッセージに非常に役立ちます。 たとえば、文法
= len:number message:.<len,len> .* {return message;}
number
= n:[0-9] {return parseInt(n);}
解析する必要があります
4[__] -> ['[', '_', '_', ']']
4[___] -> ['[', '_', '_', '_']
4[_] -> Error: expected 4 chars, got 3
これは多くのプロトコルで役立ちます。
その構文を使用することができます:
expression |min,max|
の場合、山かっこをテンプレートルールに使用できます。
まだこれを実装することを検討していますか?
ABNF範囲に似たものはどうですか?
exp * // 0 or more times
exp 1* // at least once
exp *10 // up to 10 times
exp 1*10 // 1 to 10 times
こんにちは。 解析する複雑なファイル形式があります。 半分はバイナリ、半分はASCIIです。
ここに問題の簡略化されたバージョンがあります:
KK4TesRandom
またはKK10TestATestBRandom
ロジック:
<StringIndicator><StringLength><String><otherStuff>
KK
は、文字列をマークするためのインジケーターです。 次の数字(ここで4
と10
)は文字列の長さです。 次に、文字列自体(ここでTest
とTestATestB
)。 文字列は、予測可能なパターンで終了していません。 基本的に長さ情報を使わなければなりません。 これはバイナリファイル形式の一般的なパターンだと思いますが、現在の文法で解析することは可能ですか?
ありがとう。
私はそのようなことを私のブランチ範囲-dynamic-boundaryに実装します。 文法はそう見えるでしょう:
start = len:nx data:.|len| { return data; };
nx = n:$[0-9]+ { return parseInt(n, 10); };
@ミンガンすごい! それは魅力のように機能します! 実装と短い例に感謝します。 私はいくつかのテストを行いました、そしてそれは素晴らしい働きをします。 あなたのプルリクエストがマスターに受け入れられることを願っています。
これに対する人々の回避策は何ですか? 今はPEGjsを始めたばかりなので、ハンマーでネジを回そうとしているのかもしれませんが、1桁から6桁の間で一致させようとしています:)
私は独自の実装を使用しています(構文については#267を参照してください。最終的なソリューションは、数値、変数、およびコードブロックを境界としてサポートします) 。Peggy (維持されているPEG.jsフォークのブランド変更)のPRをすぐに準備します。
最も参考になるコメント
繰り返し回数もいいです。 しかし、私は少し異なる構文を提案します。 Pegasusは、C#のみを除いて、pegjsとほぼ同じです。 ここを参照してください: https ://github.com/otac0n/Pegasus/wiki/Syntax-Guide#expressions
そして、彼らはこれを使用してこの機能を実装しました:
d<3> e<2,> f<1,5>