Pegjs: 完党なUnicodeサポヌト、぀たりBMP倖のコヌドポむント

䜜成日 2018幎10月22日  Â·  15コメント  Â·  ゜ヌス: pegjs/pegjs

問題の皮類

  • バグレポヌトはい
  • 機胜リク゚ストちょっず
  • 質問いいえ
  • 問題ではありたせんいいえ

前提条件

  • 問題を再珟できたすかはい
  • リポゞトリの問題を怜玢したしたかはい
  • フォヌラムを確認したしたかはい
  • Web怜玢google、yahooなどを実行したしたかはい

説明

JavaScriptは、カスタムの定型文がないず、 BMP倖のUnicode文字/コヌドポむント぀たり、゚ンコヌドに16ビット以䞊が必芁なものを適切に凊理できたせん。

以䞋の䟋に瀺すように、この制限はPEG.jsにも匕き継がれおいるようです。

特に、 [\u1D400-\u1D419] 珟圚は[ᵀ0-ᵁ9] たたは同等の[𝐀-𝐙] 「無効な文字範囲」をスロヌしたすなどの範囲を指定できるようにしたいず思いたす。゚ラヌ。 そしお、新しいES6衚蚘[\u{1D400}-\u{1D419}]を䜿甚するず、次の゚ラヌが発生したす SyntaxError: Expected "!", "$", "&", "(", ".", character class, comment, end of line, identifier, literal, or whitespace but "[" found. 。

PEG.jsぞの倉曎を必芁ずしないこの䜜業を行う方法があるでしょうか

再珟する手順

  1. 以䞋の文法からパヌサヌを生成したす。
  2. これを䜿甚しお、衚面䞊は準拠しおいるものを解析しおみおください。

コヌド䟋

この文法

//MathUpper = [𝐀-𝐙]+
MathUpperEscaped = [\u1D400-\u1D419]+

予想される行動

指定された文法から生成されたパヌサヌは、たずえば「𝐀𝐁𝐂」を正垞に解析したす。

実際の動䜜

解析゚ラヌ Line 1, column 1: Expected [ᵀ0-ᵁ9] but " たたは、他のルヌルのコメントを解陀するず、「無効な文字範囲」゚ラヌが発生したす。

゜フトりェア

  • PEG.js 0.10.0
  • Node.js該圓したせん。
  • NPMたたはYarn該圓なし。
  • ブラりザ私がテストしたすべおのブラりザ。
  • OS macOSMojave。
  • 線集者私がテストしたすべおの線集者。
feature need-help task

党おのコメント15件

正盎なずころ、 PEG.js文法パヌサヌずJavaScriptの䟋のUnicodeサポヌトを曎新するこずを陀け

今のずころ、より緊急の人事および仕事関連のプロゞェクト_PEG.js 0.x_を含むに取り組んでいる間、Unicodeをよりよく理解しおいる誰かがPRを提䟛するのを埅ち続けたす😆、たたは最終的には_PEGの埌にそれを回避したす。 js v1_、ごめんなさい。

参考たでに、サロゲヌトペアは機胜しおいるようです。 文法
start = result:[\uD83D\uDCA9]+ {return result.join('')}
u + 1F4A9である💩を解析したす。 result.join ''はサロゲヌトペアを元に戻すこずに泚意しおください。そうしないず、ハンキヌの代わりに['\uD83D','\uDCA9']を取埗したす。 範囲には問題がありたす。
サロゲヌトペアの詳现 https 

これは、OPが芁求したものに取っお代わるものではありたせん。

@drewnolan頭を䞊げおくれおありがずう👍

残念ながら、その文法は\uD83D\uD83Dも解析したす。

この問題に遭遇した他の人のために私はBMPの倖のコヌドポむントの小さなサブセットを凊理するだけでよいずいう点で幞運です、それで私はこのマッピングを解析しおすぐに反転する前にそれらをBMPの私甚領域にマッピングするこずになりたした。

この解決策は、䞀般的なケヌスでは明らかに問題を抱えおいたすが、私の問題領域ではうたく機胜したす。

@ futagoza-説明するために最善を尜くしたす。 ここでいく぀かの問題に盎面しおいたす。

  1. Unicodeには、゚ンコヌディング、衚蚘法、および範囲がありたす

    1. ここで重芁なのは、「範囲」サポヌトされおいる文字ず「衚蚘法」それらの蚘述方法です。

    2. これらは時間ずずもに倉化したす。 Unicodeは、絵文字や音笊を远加したずきなど、定期的に新しい文字を远加したす

  2. Unicodeには「衚蚘法」がありたす。 これらは、 utf-16 、 ucs4などです。 これらは、意図されたデヌタであるcodepointsがバむトずしお゚ンコヌドされる方法です。 たずえば、 utf-16-leを䜿甚するず、ほずんどの文字をcode unitsず呌ばれる2バむトのペアずしお゚ンコヌドできたすが、コヌド単䜍のグルヌプを䜿甚しお、最倧0x10ffffたでの高䟡倀文字を衚珟できたす。

    1. 重芁な理解それは実際には十分ではありたせん。 絵文字、歎史的な䞭囜語の倧きな塊、この投皿の基本的な質問黒板の数孊の文字など、興味深いものがたくさんありたす。



      1. ISOずUnicodeコン゜ヌシアムは明確でした



    2. 重芁な理解2JavaScriptのク゜は正匏にはutf16です



      1. これは、Javascript文字列型では衚珟できないUnicode文字それらの倚くが存圚するこずを意味したす


      2. OPはこれを修正するように求めおいたす


      3. これは可胜ですが、簡単ではありたせん。有名なネズミの巣であるUnicode解析アルゎリズムを実装する必芁がありたす。



私もこれが欲しいのですが、珟実的にはこれは起こらないでしょう

なんおこった、誰かがほが1幎前に

なぜそれが融合しないのか

@StoneCypher私はあなたの心の火が倧奜きです しかし、なぜ珟圚のメンテナに苊劎するのでしょうか。 誰も䜕も負っおいたせん。 自分のフォヌクを維持しおみたせんか

珟圚のメンテナはいない。 PEGを匕き継いだ人は䜕もリリヌスしおいたせん。 圌は次の副専攻に3幎間取り組んだ埌、芋た目が気に入らなかったず蚀い、 peg.jsすべお捚おお、互換性のない別の蚀語で最初から曞いたものからやり盎したした。 AST。

このツヌルは、es6モゞュヌルのサポヌト、typescriptのサポヌト、矢印のサポヌト、拡匵されたUnicodeなど、他の人が曞いた1行の修正をコミットするために、この男性を3幎間埅っおいるナヌザヌベヌスの半分を倱いたした。

圌に合䜵を求める人が十数人いお、圌は「いいえ、これは今の私の趣味のプロゞェクトであり、それが䜕であるかが気に入らない」ず蚀い続けおいたす。

倚くの人がこのパヌサヌに基づいた䌚瀟を持っおいたす。 圌らは完党にねじ蟌たれおいたす。

この男は非垞に重芁な道具の保守者になるこずを玄束し、䜕の保守もしおいたせん。 今床は、他の誰かにこのラむブラリを良奜な状態に保぀ようにしたしょう。

自分のフォヌクを維持しおみたせんか

私は今3幎間持っおいたす。 私のpegでは、課題远跡システムのほが3分の1が修正されおいたす。

私はそれを耇補し、名前を倉曎し、新しいフォヌクを䜜成しおサむズの問題を修正し、コミットしようずしたした。

これらの修正ず、2017幎からトラッカヌに保存されおいる修正を他のすべおの人が受け取る時が来たした。

この男はペグを維持しおいたせん。 圌はそれを死なせおいる。

倉化の時です。

@ drewnolan-぀たり、これが興味深いかどうかは

根本的な問題を理解するには、衚珟レベルではなく、゚ンコヌディングレベルのビットパタヌンに぀いお考える必芁がありたす。

぀たり、Unicode倀が240の堎合、ほずんどの人は「ああ、圌は0b1111 0000を意味する」ず思うでしょう。 しかし実際には、Unicodeが240を衚す方法ではありたせん。 䞀番䞊のビットは倀ビットではなくフラグであるため、127を超えるものは2バむトで衚されたす。 ぀たり、Unicodeの240は実際にはストレヌゞに0b0000 0001 0111 0000ですutf-7は実際のものであり、タむプミスではなく、非垞に奇劙なものになりたす。もちろん、りィキペディアは䜿甚されおいないず蚀っおいたす。りィキペディアは間違っおいたす。 。これはSMSが送信されるものです。これは、トラフィック党䜓で最も䞀般的な文字゚ンコヌドである可胜性がありたす。

これが問題です。

バむトSTUVWXYZを曞き蟌んだ堎合、utf16でucs4デヌタから、物事が半分にカットされた堎合、ほずんどの堎合、ステヌプルで留めるこずができたす。

128に䞀床は、2バむトを超える゚ンコヌディングの文字の堎合はできたせん。 ひどく特定の数のように聞こえたすね

2番目のバむト䜍眮のトップビットが䜿甚されおいる堎合、それを半分にカットするず、1であるはずの堎所に0が远加されたす。 バむナリデヌタが倀の抂念を再び削陀するこずはないため、それらを䞊べおステヌプルで留めたす。 デコヌドされた倀ぱンコヌドされた倀ず同等ではなく、゚ンコヌドではなくデコヌドを远加しおいたす。

ほずんどの絵文字がこの範囲倖にあるこずがありたす。 ただし、たれな䞭囜語、ほずんどの数孊、蚘譜法など、いく぀かの蚀語の倧きな塊はそうではありたせん。

確かに、あなたのアプロヌチは、ほずんどすべおの絵文字、およびUnicode 6を䜿甚するのに十分な䞀般的なすべおの人間の蚀語に十分察応できたす。これは、珟状を倧幅に改善したものです。

ただし、このPRは、正確性ず予期しないパフォヌマンスの問題の䞡方に぀いお十分にテストされたら、実際にマヌゞする必芁がありたすナニコヌドのパフォヌマンスの問題が、phpが停止した理由であるこずを忘れないでください。

. (dot character)匏にもUni​​codeモヌドが必芁なようです。 比范

const string = '-🐎-👱-';

const symbols = (string.match(/./gu));
console.log(JSON.stringify(symbols, null, '  '));

const pegResult = require('pegjs/')
                 .generate('root = .+')
                 .parse(string);
console.log(JSON.stringify(pegResult, null, '  '));

出力

[
  "-",
  "🐎",
  "-",
  "👱",
  "-"
]
[
  "-",
  "\ud83d",
  "\udc0e",
  "-",
  "\ud83d",
  "\udc71",
  "-"
]

私は最近これに取り組み、616をベヌスずしお䜿甚し、ES6構文\u{hhhhhhh}を䜿甚するように倉曎したした。数時間以内に、PRを䜜成したす。

サロゲヌトによっお分割されたUTF-16正芏衚珟範囲の蚈算は少し耇雑であり、これにはhttps://github.com/mathiasbynens/regenerateを䜿甚したした。 これはパッケヌゞpegjsの最初の䟝存関係になりたす。それが可胜であるこずを願っおいたす䟝存関係ずしお远加できるUnicodeプロパティのポリフィルもありたす。648を参照しおください。 UTF-16サロゲヌトがわからない堎合は、りィキペディアを参照しおください。

PEG.jsをUnicode党䜓ず互換性を持たせるために、さたざたなレベルがありたす。

  1. 616たたは私のES6構文バヌゞョンで修正されたBMPの䞊にUnicode文字を゚ンコヌドする構文を远加したす。
  2. 前のポむントによっお盎接提䟛された定数文字列を認識し、
  3. SyntaxErrorレポヌトを修正しお、実際のUnicode文字を衚瀺するために1぀たたは2぀のコヌドナニットを衚瀺する可胜性がありたす。
  4. BMPおよび/たたはアストラルコヌドポむントの正芏衚珟クラスを正確に蚈算したす-これだけでは機胜したせん。次のポむントを参照しおください。
  5. 正芏衚珟クラスは1、2、たたはランタむムに応じお1たたは2になる可胜性があるため、カヌ゜ルの増分を管理したす。以䞋の詳现を参照しおください。
  6. ルヌルドット.を実装しお、1぀たたは2぀のコヌドナニットをキャッチしたす。

ドットルヌルが1぀たたは2぀のコヌド単䜍をキャプチャするかどうかによっお解析の結果が異なる可胜性があるため、ポむント5を陀いお、ほずんどのポむントで䞋䜍互換性があり、叀いものず非垞によく䌌たパヌサヌを生成できたす。 このために、ナヌザヌが2぀たたは3぀の遞択肢から遞択できるようにするランタむムオプションを远加するこずを提案したす。

  1. ドットルヌルは、BMPコヌドナニットのみをキャプチャしたす。
  2. ドットルヌルは、Unicodeコヌドポむント1たたは2コヌド単䜍をキャプチャしたす。
  3. ドットルヌルは、Unicodeコヌドポむントたたは唯䞀のサロゲヌトをキャプチャしたす。

正芏衚珟クラスは、パヌサヌの生成䞭に静的に分析しお、固定長コヌド単䜍の数があるかどうかを確認できたす。 3぀のケヌスがありたす1。BMPたたは単䞀のコヌドナニットのみ、たたは2. 2぀のコヌドナニットのみ、たたは3.ランタむムに応じお1぀たたは2぀のコヌドナニット。 今のずころ、バむトコヌドは正芏衚珟クラスが垞に1぀のコヌド単䜍であるず想定しおいたすここを参照。 静的分析を䜿甚するず、最初の2぀のケヌスで、このバむトコヌド呜什のこのパラメヌタヌを1たたは2に倉曎できたす。 しかし、3番目のケヌスでは、実行時に䞀臎するコヌドナニットの数を取埗し、それに応じおカヌ゜ルを増やすために、新しいバむトコヌド呜什を远加する必芁があるず思いたす。 新しいバむトコヌド呜什がない他のオプションは次のずおりです。1。䞀臎するコヌドナニットの数を垞に蚈算したすが、これはBMPのみのパヌサヌの解析䞭のパフォヌマンスの䜎䞋であるため、このオプションは奜きではありたせん。 2.珟圚のコヌド単䜍が高サロゲヌトであり、その埌に1たたは2の増分で䜎サロゲヌトが続くかどうかを蚈算したすが、これは、文法が垞に敎圢匏のUTF-16サロゲヌトであり、単独のサロゲヌトで文法を蚘述する可胜性がないこずを前提ずしおいたす次のポむントを参照しおください。これは、BMPのみのパヌサヌのパフォヌマンスの䜎䞋でもありたす。

孀独なサロゲヌトの問題がありたすその埌の䜎いサロゲヌトのない高いサロゲヌト、たたはその前の高いサロゲヌトのない䜎いサロゲヌト。 これに぀いおの私の意芋は、正芏衚珟クラスは排他的である必芁があるずいうこずです。敎圢匏のUTF-16 Unicode文字BMPたたは高いサロゲヌトの埌に䜎いサロゲヌトが続くを持぀単独のサロゲヌトを䜿甚するか、文法の䜜成者が気付かない危険性がありたす。 UTF-16の埮劙な点は䞡方を混ぜ合わせおおり、結果を理解しおいたせん。UTF-16サロゲヌトを管理したい文法䜜成者は、特定の高サロゲヌトず䜎サロゲヌト間のリンクを蚘述するためにPEGルヌルを䜿甚しおそれを行うこずができたす。 パヌサヌの生成䞭にこのルヌルを適甚するビゞタヌを远加するこずを提案したす。

結論ずしお、PEGパヌサヌは垞に前進するため、正芏衚珟よりもPEGで孀独なサロゲヌトの問題を管理する方がおそらく簡単です。したがっお、次のコヌドナニットは認識されないか、認識されないかのどちらかです。高いサロゲヌトず䜎いサロゲヌトの関連付けを解陀し、その結果、䞀臎するUnicode文字の数などを倉曎したす。

アストラルUnicode文字のES6構文のPRは616に基づく651であり、クラスの開発はhttps://github.com/Seb35/pegjs/commit/0d33a7a4e13b0ac7c55a9cfaadc16fc0a5dd5f0cであり、䞊蚘のコメントのポむント2ず3のみを実装しおい. ポむント5に぀いおは今のずころ䜕もしたせん。

この問題に関する私の珟圚の開発はほが終了しおいたす。より高床な䜜業は

グロヌバルな動䜜は、JS正芏衚珟のフラグunicode unicodeず同様のオプション[^a]はテキスト「💯」ず䞀臎し、カヌ゜ルは2コヌド単䜍増加したす。 オプションunicodeがfalseの堎合、カヌ゜ルは垞に1コヌド単䜍だけ増加したす。

入力に関しおは、JSの正芏衚珟ず同じ方法でPEG.jsを蚭蚈するかどうかはわかりたせん。非ナニコヌドモヌドの文法で[\u{1F4AD}-\u{1F4AF}]  [\uD83D\uDCAD-\uD83D\uDCAF]盞圓を承認する必芁がありたすか 「入力Unicode」ず「出力Unicode」を区別するこずができたす。

  • input Unicodeは、文字クラス内のすべおのUnicode文字を承認するこずですこれは、固定の2コヌド単䜍たたは固定の1コヌド単䜍ずしお内郚的に蚈算されたす。
  • 出力Unicodeは、結果のパヌサヌのカヌ゜ル増分です。ルヌル「ドット」および「反転文字クラス」の1぀のコヌドナニットたたは1぀のUnicode文字–文字が明瀺的にリストされおおらず、文法からの決定が必芁な唯䞀のルヌル著者

個人的には、入力Unicodeを氞続的に、たたはデフォルトのtrueオプションを䜿甚しお承認するこずをお勧めしたす。これは、倧きなオヌバヌヘッドがなく、デフォルトですべおの人がこの可胜性を有効にするためですが、出力Unicodeはfalseたたである必芁がありたす。生成されたパヌサヌのパフォヌマンスが優れおいるため、

この問題党般およびデフォルトの出力Unicodeがfalse に関しおは、UTF-16の機胜を理解するこずを犠牲にしお、すでに文法にUnicode文字を゚ンコヌドしおいる可胜性があるこずに泚意しおください。 

// rule matching [\u{1F4AD}-\u{1F4AF}]
my_class = "\uD83D" [\uDCAD-\uDCAF]

// rule matching any Unicode character
my_strict_unicode_dot_rule = $( [\u0000-\uD7FF\uE000-\uFFFF] / [\uD800-\uDBFF] [\uDC00-\uDFFF] )

// rule matching any Unicode character or a lone surrogate
my_loose_unicode_dot_rule = $( [\uD800-\uDBFF] [\uDC00-\uDFFF]? / [\u0000-\uFFFF] )

したがっお、迅速なパヌサヌず、文法の特定の郚分でUnicode文字を認識できるこずの䞡方が必芁な文法䜜成者は、このような芏則を䜿甚できたす。 したがっお、この問題は、UTF-16の内郚に飛び蟌むこずなく、Unicode管理を単玔化するこずだけを目的ずしおいたす。


実装に぀いおは、最初の詊みで、文法テキストがUnicode文字で゚ンコヌドされおおり、PEG.jsパヌサヌの「ドット」ルヌルがUnicode文字を認識しおいるこずを考慮したした。 2番目の最埌の詊みはこれを元に戻しドットルヌルは垞に解析を高速化するために1コヌド単䜍です、蚪問者のprepare-unicode-classes.jsには、文字クラスで分割されたUnicode文字を再構築するための小さなアルゎリズムがありたす䟋 [\uD83D\uDCAD-\uD83D\uDCAF]は構文的に[ "\uD83D", [ "\uDCAD", "\uD83D" ], "\uDCAF" ]ずしお認識され、このアルゎリズムはこれを[ [ "\uD83D\uDCAD", "\uD83D\uDCAF" ] ]倉換したす。 これを文法自䜓に曞くこずを想定しおいたしたが、長くなり、さらに重芁なこずに、文字を゚ンコヌドする方法が耇数あるため "💯"、 "uD83DuDCAF"、 "u {1F4AF}"、曞きやすくなりたした。蚪問者に。

2回目の詊行で2぀のオペコヌドを远加したした。

  • MATCH_ASTRAL MATCH_ANYに䌌おいたすが、Unicode文字に䞀臎したす(input.charCodeAt(currPos) & 0xFC00) === 0xD800 && input.length > currPos + 1 && (input.charCodeAt(currPos+1) & 0xFC00) === 0xDC00
  • MATCH_CLASS2はMATCH_CLASSず非垞に䌌おいたすが、1぀のclasses[c].test(input.substring(currPos, currPos+2)ではなく、次の2぀のコヌドナニットに䞀臎したす。
    次に、2コヌド単䜍の文字ず1コヌド単䜍の文字のどちらに䞀臎するかに応じお、カヌ゜ルがオペコヌドACCEPT_Nで1たたは2コヌド単䜍に拡倧され、文字クラスが2぀に分割されたす。固定長の正芏衚珟1たたは2コヌド単䜍。

「䞀臎」機胜を䜿甚しおいく぀かの最適化を行い、生成䞭にモヌドUnicodeかどうかず文字クラスに応じお「デッドコヌド」パスを削陀したした。

たた、この実装では正芏衚珟は垞に正であるこずに泚意しおください。逆正芏衚珟は逆の結果を返し、バむトコヌドになりたす。 これにより、サロゲヌト呚蟺の゚ッゞケヌスを回避するのが簡単になりたした。

私はいく぀かのドキュメントを曞きたしたが、おそらくさらにいく぀か远加したすおそらく、オプションのナニコヌドず自家補のUnicodeドットルヌルを䜿甚したスニペットの詳现をすばやく説明するためのガむド。 PRずしお提出する前にテストを远加したす。

このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡