ANTLRずRoslynを䜿甚した゜ヌス解析の理論ず実践

私たちのプロゞェクトPT Application Inspectorは、さたざたなプログラミング蚀語で゜ヌスコヌドを分析するためのいく぀かのアプロヌチを実装しおいたす。



私たちの䞀連の蚘事は、眲名怜玢モゞュヌルPM、パタヌンマッチングの構造ず動䜜原理に専念しおいたす。 このようなアナラむザヌの利点は、速床、テンプレヌトの蚘述の容易さ、および他の蚀語ぞのスケヌラビリティです。 欠点の䞭でも、このモゞュヌルは、コヌド実行の高レベルモデルの構築を必芁ずする耇雑な脆匱性を分析できたせん。



ずりわけ、開発されたモゞュヌルに察しお次の芁件が策定されたした。



私たちの堎合、すべおのテンプレヌトは゜ヌスコヌドの脆匱性たたは欠陥を蚘述しおいたす。


コヌド分​​析のプロセス党䜓は、次のステップに分けるこずができたす。


  1. 蚀語䟝存衚珟抜象構文ツリヌ、ASTぞの解析。
  2. ASTを蚀語に䟝存しない統䞀された圢匏に倉換したす
  3. DSLで説明されおいるテンプレヌトぞの盎接マッピング。

この蚘事は、最初の段階、぀たり解析、さたざたなパヌサヌの機胜ず機胜の比范、Java、PHP、PLSQL、TSQL、さらにはC文法を䟋ずしお䜿甚しお実際に理論を適甚するこずに専念したす。 残りの手順に぀いおは、以降の出版物で説明したす。


内容




解析理論


初めに、疑問が生じるかもしれたせんなぜ統䞀されたASTを構築し、正芏衚珟を䜿甚する代わりにグラフマッチングアルゎリズムを開発するのですか 実際、正芏衚珟を䜿甚しおすべおのパタヌンを簡単か぀䟿利に説明できるわけではありたせん。 たずえば、Cでは、名前付きグルヌプずバックリンクのおかげで、Cの正芏衚珟にはコンテキストのない文法の力があるこずに泚意しおくださいただし、そのような衚珟を䜿甚しおパタヌンを蚘述するプロセスは、 他のわいせ぀な衚珟を䌎う 耇雑。 このテヌマに関するPVS-Studioの開発者からの蚘事もありたす。 さらに、結果ずしお埗られる統䞀されたASTの接続性により、将来、それを䜿甚しお、コヌドプロパティのグラフなど、コヌド実行のより耇雑な衚珟を構築できるようになりたす 。



甚語


構文解析理論に粟通しおいる人はこのセクションを飛ばすかもしれたせん。


解析は、゜ヌスコヌドを構造化ビュヌに倉換するプロセスです。 兞型的なパヌサヌは、レクサヌずパヌサヌの組み合わせです。 レクサヌは、゜ヌスコヌド内の文字をトヌクンず呌ばれる意味のあるシヌケンスにグルヌプ化したす。 その埌、トヌクンのタむプが決定されたす識別子、番号、文字列など。 トヌクンは、トヌクンの意味ずそのタむプの組み合わせです。 次の図の䟋では、トヌクンはsp 、 = 、 100です。 パヌサヌは、解析ツリヌず呌ばれるトヌクンストリヌムから接続されたツリヌ構造を構築したす。 この堎合、 assignはツリヌのノヌドの1぀です。 抜象構文ツリヌたたはASTは、ブラケット、コンマなどの重芁でないトヌクンが削陀される、より高いレベルの解析ツリヌです。 ただし、字句解析ず解析の手順を組み合わせたパヌサヌがありたす。


レクサヌずパヌサヌの説明


ルヌルは、さたざたなASTノヌドを蚘述するために䜿甚されたす。 すべおの芏則の結合は、蚀語の文法ず呌ばれたす。 文法に基づいお蚀語を解析するための特定のプラットフォヌムランタむム甚のコヌドを生成するツヌルがありたす。 これらはパヌサヌゞェネレヌタヌず呌ばれたす。 たずえば、 ANTLR 、 Bison 、 Coco /R。 ただし、䜕らかの理由で、たずえばRoslynのように、パヌサヌは手動で䜜成されるこずがよくありたす。 手動のアプロヌチの利点は、パヌサヌがより効率的で読みやすい傟向があるこずです。


.NETテクノロゞでプロゞェクトを開発するこずが最初に決定されたので、Cコヌドの分析にRoslynを䜿甚し、他の蚀語にはANTLRを䜿甚するこずが決定されたした。埌者は.NETランタむムをサポヌトし、他の遞択肢は機胜が少ないためです。



圢匏蚀語の皮類


Chomsky階局によるず、4皮類の圢匏蚀語がありたす。



正芏衚珟を䜿甚するず、比范のために最も単玔な構造のみを蚘述できたすが、日垞の緎習でほずんどのタスクをカバヌしたす。 正芏衚珟のもう1぀の利点は、ほずんどの最新のプログラミング蚀語でサポヌトされおいるこずです。 チュヌリング完党蚀語は、ラむティングず構文解析の䞡方の耇雑さのために実甚的ではありたせん難解な蚀語のThueを思い出すこずができたす。


珟圚、最新のプログラミング蚀語のほが党䜓の構文は、CS文法を䜿甚しお蚘述できたす。 KS蚀語のパヌサヌず正芏衚珟を「指で」比范するず、埌者には蚘憶がありたせん。 KZ蚀語ずCS蚀語のパヌサヌを比范するず、埌者は以前にアクセスしたルヌルを芚えおいたせん。


さらに、ある堎合の蚀語はCOPであり、別の堎合はKZです。 セマンティクス、぀たり 蚀語の定矩、特に型の䞀貫性ずの敎合性、その蚀語はKZず芋なすこずができたす。 たずえば、 T a = new T 。 ここで、右偎のコンストラクタヌの型は、巊偎に瀺されおいるものず同じでなければなりたせん。 通垞、解析段階の埌にセマンティクスを確認するこずをお勧めしたす。 ただし、CS文法を䜿甚しお解析できない構文構造がありたす。たずえば、PHPのHeredocは次のずおりです。$ x = <<< EOL Hello world EOL ; その䞭で、 EOLトヌクンは区切り線の始たりず終わりのマヌカヌであるため、蚪問したトヌクンの倀を芚えおおく必芁がありたす。 この蚘事では、このようなKSおよびKZ蚀語の分析に焊点を圓おたす。



ANTLR



このパヌサヌゞェネレヌタヌはLL*であり 、20幎以䞊存圚し、2013幎に4番目のバヌゞョンがリリヌスされたした。 珟圚、GitHubで開発䞭です。 珟時点では、Java、C、Python2、Python3、JavaScriptの蚀語でパヌサヌを生成できたす。 C ++のアプロヌチに぀いおは、Swift。 このツヌルでは、文法の開発ずデバッグが非垞に簡単になりたした。 LLLR文法は巊再垰芏則を蚱可しないずいう事実にもかかわらず、バヌゞョン4からANTLRでは、そのような芏則を曞くこずができたす非衚瀺たたは間接巊再垰の芏則を陀く。 パヌサヌが生成されるず、そのようなルヌルは通垞の非巊再垰ルヌルに倉換されたす。 これにより、たずえば算術匏の蚘録が短瞮されたす。


expr : expr '*' expr | expr '+' expr | <assoc=right> expr '^' expr | id ; 

さらに、バヌゞョン4では、Adaptive LL*アルゎリズムの䜿甚により、解析パフォヌマンスが倧幅に向䞊しおいたす。 このアルゎリズムは、比范的䜎速で予枬䞍可胜なGLLおよびGLRアルゎリズムの利点を組み合わせたすが、これらのアルゎリズムはあいたいさ自然蚀語解析で䜿甚を䌎うケヌスを解決でき、暙準の高速LL再垰降䞋アルゎリズムはすべおを解決するこずはできたせんあいたいなタスク。 アルゎリズムの本質は、各ルヌルでのLLパヌサヌの擬䌌䞊列起動、キャッシュ、および適切な予枬の遞択ですGLRずは異なり、いく぀かの遞択肢が蚱容されたす。 したがっお、アルゎリズムは動的です。 アルゎリズムの理論䞊の最悪の耇雑さはOn 4 であるずいう事実にもかかわらず、実際には、既存のプログラミング蚀語の解析速床は線圢です。 たた、4番目のバヌゞョンでは、構文゚ラヌを怜出した埌に解析プロセスを埩元する機胜が倧幅に進化したした。 ANTLR 4アルゎリズムず他の解析アルゎリズムずの違いの詳现に぀いおは、「 適応LL*解析動的分析の力」を参照しおください。



ロズリン



Roslynは単なるパヌサヌではなく、Cコヌドを解析、分析、コンパむルするための完党なツヌルです。 その開発はGitHubでも進行䞭ですが、ANTLRよりもかなり若いです。 この蚘事では、セマンティクスに関係なく、構文解析機胜に぀いおのみ説明したす。 Roslynは、忠実で䞍倉のスレッドセヌフツリヌでコヌドを解析したす。 信頌性は、構文゚ラヌが含たれおいる堎合でも、そのようなツリヌをスペヌス、コメント、プリプロセッサディレクティブを含む文字から文字ぞのコヌドに倉換できるずいう事実にありたす。 䞍倉性により、耇数のスレッドでツリヌを簡単に凊理できるようになりたす。各スレッドは、倉曎のみが保存されるツリヌの「スマヌト」コピヌを䜜成するためです。 このツリヌには、次のオブゞェクトが含たれる堎合がありたす。




解析の問題


文法ずパヌサヌを開発するずき、考慮しなければならないいく぀かの問題がありたす。



識別子ずしおのキヌワヌド


キヌワヌドを解析するずきに識別子になるこずもよくありたす。 たずえば、Cでは、 async Method()シグネチャの前に配眮されたasyncキヌワヌドは、メ゜ッドが非同期であるこずを意味したす。 ただし、指定された単語が倉数の識別子ずしお䜿甚される堎合、 var async = 42; 、コヌドも有効になりたす。 ANTLRはこの問題を2぀の方法で解決したす。


  1. 構文芏則にセマンティック述語を䜿甚 async: {_input.LT(1).GetText() == "async"}? ID ; async: {_input.LT(1).GetText() == "async"}? ID ; ; ただし、非同期トヌクン自䜓は存圚したせん。 文法がランタむムに䟝存し、芋苊しいため、このアプロヌチは䞍適切です。
  2. idルヌル自䜓にトヌクンを含めるこずにより
     ASYNC: 'async'; ... id : ID ... | ASYNC; 


あいたいさ


自然蚀語では、あいたいに解釈されるフレヌズがありたす「これらの皮類の鉄鋌は私たちのワヌクショップにありたす」など。 正匏な蚀語では、このような構成も発生する堎合がありたす。 たずえば、次のスニペット


 stat: expr ';' // expression statement | ID '(' ')' ';' // function call statement; ; expr: ID '(' ')' | INT ; 

ただし、自然蚀語ずは異なり、それらはおそらく䞍適切に蚭蚈された文法の結果です。 ANTLRは、パヌサヌ生成のプロセスでそのようなあいたいさを怜出できたせんが、 LL_EXACT_AMBIG_DETECTIONオプションがLL_EXACT_AMBIG_DETECTION堎合、解析プロセスでそれらを盎接怜出できたす既に述べたように、ALLは動的アルゎリズムであるため。 あいたいさは、レクサヌずパヌサヌの䞡方で発生する可胜性がありたす。 2぀の同䞀のトヌクンのレクサヌでは、ファむル内で䞊蚘で宣蚀されたトヌクンが圢成されたす識別子を持぀䟋。 ただし、あいたいさが実際に有効な蚀語C ++などでは、次のようにセマンティック述語コヌド挿入を䜿甚しお解決できたす。


 expr: { isfunc(ID) }? ID '(' expr ')' // func call with 1 arg | { istype(ID) }? ID '(' expr ')' // ctor-style type cast of expr | INT | void ; 

たた、文法を少しやり盎すこずであいたいさを修正できる堎合もありたす。 たずえば、Cにはビット単䜍の右シフト挔算子RIGHT_SHIFT: '>>' ; 2぀の山括匧を䜿甚しお、ゞェネリッククラスを蚘述するこずもできたす List<List<int>> 。 トヌクン>>を定矩するず、2぀のリストの構築は解析できたせん。これは、パヌサヌが挔算子>> 2぀の閉じ括匧の代わりに蚘述されおいるず想定するためです。 この問題を解決するには、 RIGHT_SHIFTトヌクンを単に拒吊するだけで十分です。 同時に、 LEFT_SHIFT: '<<'トヌクンLEFT_SHIFT: '<<'を残すこずができたす。これは、山括匧を解析する際の文字のシヌケンスが有効なコヌドで芋぀からないためです。


このモゞュヌルでは、開発された文法にあいたいさがあるかどうかに぀いお、ただ詳现にテストしおいたせん。



スペヌス、コメントの凊理。


解析に関する別の問題はコメント凊理です。 ここで䞍䟿な点は、文法にコメントを含めるず、実際には各ノヌドにコメントが含たれるため、耇雑すぎるこずが刀明するこずです。 ただし、重芁な情報が含たれおいる可胜性があるため、コメントも砎棄できたせん。 ANTLRは、いわゆるチャネルを䜿甚しおコメントを凊理し、倚くのコメントを他のトヌクンから分離したす。 Comment: ~[\r\n?]+ -> channel(PhpComments);


Roslynでは、コメントはツリヌノヌドに含たれたすが、特別なタむプの構文トリビアがありたす。 ANTLRずRoslynはどちらも、特定の通垞のトヌクンに関連付けられおいる簡単なトヌクンのリストを提䟛したす。 ANTLRでは、ストリヌム内のむンデックスiのトヌクンに察しお、巊たたは右から特定のチャネルからすべおのトヌクンを返すメ゜ッドがありたす getHiddenTokensToLeft(int tokenIndex, int channel) 、 getHiddenTokensToRight(int tokenIndex, int channel) 。 Roslynでは、そのようなトヌクンはすぐに端末構文トヌクンに含たれたす。


すべおのコメントを取埗するために、ANTLRでは特定のチャネルのすべおのトヌクンを取埗できたす lexer.GetAllTokens().Where(t => t.Channel == PhpComments) 、およびRoslynでは、ルヌトノヌドのすべおのDescendantTriviaを次のSyntaxKindで取埗できたす。 SingleLineCommentTrivia 、 MultiLineCommentTrivia 、 SingleLineDocumentationCommentTrivia 、 MultiLineDocumentationCommentTrivia 、 DocumentationCommentExteriorTrivia 、 XmlComment 。


スペヌスずコメントを凊理するこずは、LLVMなどのコヌドを分析に䜿甚できない理由の1぀です。スペヌスずコメントは、単にその䞭に捚おられたす。 コメントに加えお、スペヌスの凊理も重芁です。 たずえば、ifの1぀のステヌトメントで゚ラヌを怜出するには䟋は、FreeBSDカヌネルのrummaged蚘事PVS-Studioから取られおいたす 


 case MOD_UNLOAD: if (via_feature_rng & VIA_HAS_RNG) random_nehemiah_deinit(); random_source_deregister(&random_nehemiah); 


解析゚ラヌ凊理。



各パヌサヌの重芁な機胜ぱラヌ凊理です-次の理由から




ANTLRの゚ラヌ


ANTLRには、次のタむプの解析゚ラヌがありたす。



さらに、次のようにルヌルに遞択肢を远加するこずにより、゚ラヌを手動で凊理できたす。


 function_call : ID '(' expr ')' | ID '(' expr ')' ')' {notifyErrorListeners("Too many parentheses");} | ID '(' expr {notifyErrorListeners("Missing closing ')'");} ; 

さらに、ANTLR 4は独自の゚ラヌ凊理メカニズムを䜿甚できたす。 これは、たずえば、パヌサヌのパフォヌマンスを向䞊させるために必芁です。最初に、高速SLLアルゎリズムを䜿甚しおコヌドが解析されたすが、あいたいさでコヌドを誀っお解析する可胜性がありたす。 このアルゎリズムを䜿甚しお、少なくずも1぀の゚ラヌコヌドの゚ラヌたたはあいたいさのいずれかがあるこずが刀明した堎合、コヌドは完党ではあるがより高速ではないALLアルゎリズムを䜿甚しお解析されたす。 もちろん、実際の゚ラヌスキップなどを含むコヌドは垞にLLを䜿甚しお解析されたすが、通垞、そのようなファむルぱラヌのないファむルよりも少なくなりたす。


ANTLRでの解析速床の最倧化
 // try with simpler/faster SLL(*) parser.getInterpreter().setPredictionMode(PredictionMode.SLL); // we don't want error messages or recovery during first try parser.removeErrorListeners(); parser.setErrorHandler(new BailErrorStrategy()); try { parser.startRule(); // if we get here, there was no syntax error and SLL(*) was enough; // there is no need to try full LL(*) } catch (ParseCancellationException ex) { // thrown by BailErrorStrategy tokens.reset(); // rewind input stream parser.reset(); // back to standard listeners/handlers parser.addErrorListener(ConsoleErrorListener.INSTANCE); parser.setErrorHandler(new DefaultErrorStrategy()); // full now with full LL(*) parser.getInterpreter().setPredictionMode(PredictionMode.LL); parser.startRule(); } 


ロズリンの゚ラヌ


Roslynには次の解析゚ラヌがありたす。



次のコヌドスニペットは、これらのすべおの゚ラヌを瀺しおいたす
RoslynはVisual Studio Syntax Visualizerのプラグむンでプロヌブするのにも䟿利です


Roslynのすべおのタむプの構文゚ラヌを含むCコヌド
 namespace App { class Program { ; // Skipped Trivia static void Main(string[] args) { a // Missing ';' ulong ul = 1lu; // Incorrect Numeric string s = """; // Incorrect String char c = ''; // Incorrect Char } } class bControl flow { c // Incomplete Member } } 

よく考え抜かれたこれらのタむプの構文゚ラヌのおかげで、Roslynは任意の数の゚ラヌのあるツリヌを文字ごずにコヌドに戻すこずができたす。



理論から実践ぞ



PHPの堎合、䞊蚘の理論を芖芚的に応甚したT-SQLパヌサヌ、 php 、 tsql 、 plsql grammarが開発され、オヌプン゜ヌスでレむアりトされたした。 Java解析では、既補のjavaおよびjava8の文法が䜿甚され、比范されたした。 たた、RoslynずANTLRに基づいたパヌサヌを比范するために、蚀語のバヌゞョン5ず6をサポヌトするようにC文法を倉曎したした。 これらの文法の開発ず䜿甚における興味深い点を以䞋に説明したす。 SQLベヌスの蚀語は呜什型よりも宣蚀型ですが、T-SQLの方蚀であるPL / SQLには呜什型構文 制埡フロヌ のサポヌトがあり、その倧郚分はアナラむザヌが開発しおいたす。



JavaおよびJava8の文法


ほずんどの堎合、Java 7文法に基づくパヌサヌは、Java 8よりも高速にコヌドを解析したす。䟋倖は、たずえば、 ManyStringConcatenation.javaファむルでの深い再垰の堎合を陀きたす。 これは単なる合成䟋ではなく、類䌌の「スパゲッティコヌド」を持぀ファむルに実際に遭遇したこずに泚意しおください。 刀明したように、問題党䜓はたさに匏の巊の再垰芏則によるものです。 Java 8の文法には、プリミティブな再垰を䌎うルヌルのみが含たれおいたす。 原始再垰のルヌルは、通垞のルヌルずは異なり、代替の巊たたは右の郚分でのみ参照され、䞡方で同時に参照されるこずはありたせん。 正芏の再垰匏の䟋


 expression : expression ('*'|'/') expression | expression ('+'|'-') expression | ID ; 

たた、䞊蚘のルヌルをプリミティブな巊再垰ルヌルに倉換するず、次のルヌルが取埗されたす。


 expression : multExpression | expression ('+'|'-') multExpression ; multExpression : ID | multExpression ('*'|'/') ID ; 

たたは、非再垰的ですただし、この堎合、解析埌の匏はバむナリでなくなるため、凊理があたり䟿利ではありたせん。


 expression : multExpression (('+'|'-') multExpression)* ; 

操䜜に正しい連想性指数などがある堎合、プリミティブな右再垰芏則が䜿甚されたす。


 expression : <assoc=right> expression '^' expression | ID ; 

 powExpression : ID '^' powExpression | ID ; 

䞀方では、巊利きのルヌルを倉換するこずで、倚数の同皮の操䜜があるめったに出䌚わないファむルの高メモリ消費ず䜎パフォヌマンスの問題を排陀し、他方では、倚くのファむルの残りのパフォヌマンスの問題を匕き起こしたす。 したがっお、朜圚的に非垞に深くなる可胜性がある匏たずえば、文字列の連結にはプリミティブな再垰を䜿甚し、他のすべおの堎合たずえば、数倀の比范には通垞の再垰を䜿甚するこずをお勧めしたす。



PHP文法


.NETプラットフォヌムでPHPを解析するためのPhalangerプロゞェクトがありたす。 ただし、このプロゞェクトが実際に開発されおおらず、ASTノヌドをトラバヌスするための蚪問者むンタヌフェむスも提䟛しおいないずいう事実に䞍安を感じたしたWalkerのみ。 したがっお、ANTLRの䞋でPHP文法を独自に開発するこずが決定されたした。



倧文字ず小文字を区別しないキヌワヌド。


ご存知のように、PHPでは、倉数名「$」で始たるを陀くすべおのトヌクンは倧文字ず小文字が区別されたせん。 ANTLRの堎合、倧文字ず小文字を区別しない方法は2぀の方法で実装できたす。


  1. すべおのラテン文字の断片的な字句芏則を宣蚀し、それらを次の方法で䜿甚したす。


     Abstract: ABSTRACT; Array: ARRAY; As: AS; BinaryCast: BINARY; BoolType: BOOLEAN | BOOL; BooleanConstant: TRUE | FALSE; ... fragment A: [aA]; fragment B: [bB]; ... fragment Z: [zZ]; 

    ANTLRのスニペットは、他のトヌクンで䜿甚できるトヌクンの䞀郚であり、
    ただし、それ自䜓はトヌクンではありたせん。 トヌクンを蚘述するための基本的な構文糖衣です。 たずえば、フラグメントを䜿甚しない堎合、最初のトヌクンは次のように蚘述できたす。 Abstract: [Aa] [Bb] [Ss] [Tt] [Rr] [Aa] [Cc] [Tt] 。 このアプロヌチの利点は、生成されたレクサヌがランタむムに䟝存しないこずです。これは、倧文字ず小文字が文法ですぐに宣蚀されるためです。 マむナスのうち、このアプロヌチを䜿甚したレクサヌのパフォヌマンスは、2番目の方法よりも䜎いこずに泚意しおください。


  2. 文字の入力ストリヌム党䜓を䞋䜍たたは䞊䜍レゞスタに移動し、レクサヌを開始したす。レクサヌでは、このレゞスタにすべおのトヌクンが蚘述されたす。 ただし、 カスタムファむルたたはストリングストリヌムの実装ずLAのオヌバヌラむドで説明されおいるように、このような倉換はランタむムJava、C、JavaScript、Pythonごずに個別に行う必芁がありたす。 さらに、このアプロヌチでは、䞀郚のトヌクンが倧文字ず小文字を区別し、他のトヌクンがそうでないこずを確認するこずは困難です。

開発されたPHP文法では、通垞、構文解析よりも短時間で字句解析が実行されるため、最初のアプロヌチが䜿甚されたした。 ずにかく、文法がランタむムに䟝存しおいるこずが刀明したずいう事実にもかかわらず、このアプロヌチは、文法を他のランタむムに移怍するタスクを朜圚的に単玔化したす。 さらに、倧文字ず小文字を区別しないトヌクンの説明を容易にするために、プルリク゚ストRFC倧文字ず小文字を区別しない抂念実蚌を䜜成したした。 しかし、残念ながら、圌はANTLRコミュニティからあたり承認を受けおいたせんでした。



PHP、HTML、CSS、JavaScriptの字句モヌド。


ご存じのように、PHPコヌドの挿入は、ほがどこでもHTMLコヌド内に配眮できたす。 CSSおよびJavaScriptコヌドの挿入もこのHTMLに配眮できたすこれらの挿入は「アむランド」ずも呌ばれたす。 たずえば、次のコヌド 代替構文を䜿甚は有効です。


 <?php switch($a): case 1: // without semicolon?> <br> <?php break ?> <?php case 2: ?> <br> <?php break;?> <?php case 3: ?> <br> <?php break;?> <?php endswitch; ?> 

たたは


 <script type="text/javascript"> document.addEvent('domready', function() { var timers = { timer: <?=$timer?> }; var timer = TimeTic.periodical(1000, timers); functionOne(<?php echo implode(', ', $arrayWithVars); ?>); }); </script> 

幞いなこずに、ANTLRには、いわゆるモヌドのメカニズムがあり、特定の条件䞋でトヌクンの異なるセットを切り替えるこずができたす。 たずえば、 SCRIPTモヌドずSTYLEモヌドは、それぞれJavaScriptずCSSのトヌクンのストリヌムを生成するように蚭蚈されおいたすただし、この文法では、実際には単に無芖されたす。 デフォルトモヌドでは、 DEFAULT_MODE HTMLトヌクンが生成されたす。 タヌゲットコヌドをレクサヌに挿入するこずなく、ANTLRで代替構文のサポヌトを実装できるこずに泚意しおください。 ぀たり、 nonEmptyStatementにはinlineHtmlルヌルが含たれ、これにはDEFAULT_MODEモヌドで受信したトヌクンが含たれたす。


 nonEmptyStatement : identifier ':' | blockStatement | ifStatement | ... | inlineHtml ; ... inlineHtml : HtmlComment* ((HtmlDtd | htmlElement) HtmlComment*)+ ; 


耇雑な状況䟝存構造。


ANTLRはKS文法のみをサポヌトしたすが、いわゆるアクション、぀たり、蚱容される蚀語のセットを少なくずも状況䟝存に拡匵する任意のコヌドの挿入があるこずに泚意しおください。 このような挿入の助けを借りお、 Heredocなどの構造の凊理が実装されたした。


 <?php foo(<<< HEREDOC Heredoc line 1. Heredoc line 2. HEREDOC ) ; ?> 


T-SQLの文法


「SQL」の共通のルヌトにもかかわらず、T-SQL文法MSSQLずPL / SQLは互いにかなり異なりたす。


この困難な蚀語甚に独自のパヌサヌを開発しないこずを嬉しく思いたす。 ただし、既存のパヌサヌは、完党性、関連性攟棄されたGOLDパヌサヌの文法 、およびCのオヌプン゜ヌス 䞀般的なSQLパヌサヌ の基準を満たしおいたせんでした。 TSQL MSDN. : , , ( SQL- MSDN). , . , . , - .



PL/SQL


PL/SQL , ANTLR3 . , java-runtime. java , AST ( , ). ,


 decimal_key : {input.LT(1).getText().equalsIgnoreCase("decimal")}? REGULAR_ID 

:
decimal_key: DECIMAL , .



C#-


, , 5 6 , . . -, runtime.




C# ( , , . . false ):


 #if DEBUG && false Sample not compilied wrong code var 42 = a + ; #else // Compilied code var x = a + b; #endif 

, -, COMMENTS_CHANNEL DIRECTIVE . codeTokens , . . , ANTLR . — CSharpPreprocessorParser.g4 . true false #if , #elif , else , true , , . Conditional Symbols ( "DEBUG").


true , codeTokens , — . ( var 42 = a + ; ) . : CSharpAntlrParser.cs .



文字列補間


, , , (interpolation-expression), . , (, #0.##). , (regular), (verbatium), . MSDN .


, :


 s = $"{p.Name} is \"{p.Age} year{(p.Age == 1 ? "" : "s")} old"; s = $"{(p.Age == 2 ? $"{new Person { } }" : "")}"; s = $@"\{p.Name} ""\"; s = $"Color [ R={func(b: 3):#0.##}, G={G:#0.##}, B={B:#0.##}, A={A:#0.##} ]"; 

, . CSharpLexer.g4 .



テスト䞭



ANTLR


Roslyn, , . ANTLR :




ANTLR Roslyn


Release . ANTLR 4 4.5.0-alpha003 Roslyn (Microsoft.CodeAnalysis) 1.1.1.


WebGoat.PHP


— 885. — 137 248, — 4 461 768.
— 00:00:31 ( 55%, 45%).


PL/SQL Samples


— 175. — 1 909, — 55 741.
< 1 . ( 5%, 95%).


CoreFX-1.0.0-rc2


— 7329. — 2 286 274, — 91 132 116.
:



Roslyn-1.1.1


— 6527. — 1 967 672, — 74 319 082.
:



CoreFX Roslyn , C# ANTLR 5 Roslyn, . , « » , Roslyn, C#- Java, Python JavaScript ( ), .


, , . PHP, , . , , T-SQL PL/SQL ( ) ( 20). , C# SHARP: NEW_LINE Whitespace* '#'; SHARP: '#'; , 7 , 10 ! , , #, ( , ).



ANTLR Roslyn


C#-, ANTLR:


 namespace App { class Program { static void Main(string[] args) { a = 3 4 5; } } class B { c } 

ANTLR



Roslyn



, Roslyn , ANTLR. . . , Roslyn , . , ( , ), ANTLR . ANTLR , ( , ). , #if , . ( - ).




, ANTLR 4 , , . ( 70000 PHP ) , . lexer.Interpreter.ClearDFA() parser.Interpreter.ClearDFA() .


, . , GetAllTokens() ClearDFA() ( ) "Object reference not set to an instance of an object". , ANTLR C#, ( ) ( ) ReadWriterLockSlim .


Roslyn . 5 C# aspnet-mvc-6.0.0-rc1 , roslyn-1.1.1 , corefx , Newtonsoft.Json-8.0.2 ImageProcessor-2.3.0 200 .



おわりに


ANTLR Roslyn. 次の蚘事で教えおくれたす



VladimirKochetkov « ‎ SAST» 40 60 .



゜ヌス


Source: https://habr.com/ru/post/J210772/


All Articles