タグ付けされた質問 「lexer」

4
Parser Combinatorを使用する場合 パーサージェネレーターを使用する場合
最近、パーサーの世界を深く掘り下げて、独自のプログラミング言語を作成したいと考えています。 しかし、パーサーを作成するには、パーサージェネレーターとパーサーコンビネーターという2つの異なるアプローチが存在することがわかりました。 興味深いことに、どのケースでどのアプローチが優れているかを説明したリソースを見つけることができませんでした。むしろ、資源(および人)の多くは、私は、他のアプローチを知っているだけで説明していない主題について質問彼らのようなアプローチをアプローチし、他のすべてのに言及していません。 有名なドラゴンブックは字句/スキャンに入ると、(f)LEXに言及しているが、すべてのパーサコンビネータを言及していません。 言語実装パターンは、Javaで構築されたANTLR Parser Generatorに大きく依存しており、Parser Combinatorsについては一切言及していません。 HaskellのParser CombinatorであるParsecのParsec入門チュートリアルでは、Parser Generatorsについてはまったく言及していません。 Boost :: spirit、最も有名なC ++ Parser Combinatorは、Parser Generatorsについてまったく言及していません。 パーサーコンビネーターを発明した可能性のある優れた説明ブログ投稿では、パーサージェネレーターについては一切言及していません。 簡単な概要: パーサージェネレーター パーサージェネレーターは、Extended Backus-Naur形式の方言であるDSLで記述されたファイルを受け取り、それを(コンパイル時に)このDSLで記述された入力言語のパーサーにできるソースコードに変換します。 これは、コンパイルプロセスが2つの別々のステップで実行されることを意味します。興味深いことに、パーサージェネレーター自体もコンパイラーです(そしてそれらの多くは実際に自己ホスト型です)。 パーサーコンビネーター パーサーコンビネーターは、すべてがパラメーターとして入力を受け取るパーサーと呼ばれる単純な関数を記述し、一致する場合、この入力の最初の文字を抜き取ります。パーサーがこの入力から何も解析できなかった場合は、タプルを返します。タプル(result, rest_of_input)はresult空(nilまたはNothing)の場合があります。例はdigitパーサーです。もちろん、他のパーサーは、パーサーを最初の引数(最後の引数は入力文字列のまま)として、それらを結合many1できます。 言うまでもなく、新しいパーサーを作成するために、もちろん(compose)digitとを組み合わせることができmany1ますinteger。 また、choiceパーサーのリストを取得し、それぞれを順に試す、より高レベルのパーサーを作成することもできます。 このようにして、非常に複雑なレクサー/パーサーを構築できます。演算子のオーバーロードをサポートする言語では、ターゲット言語で直接記述されていても、EBNFに非常によく似ています(ターゲット言語のすべての機能を使用できます)。 単純な違い 言語: パーサージェネレーターは、EBNFのようなDSLと、これらのステートメントが一致したときに生成するコードの組み合わせで記述されます。 パーサーコンビネーターは、ターゲット言語で直接記述されています。 字句解析/解析: パーサージェネレーターは、「レクサー」(文字列をタグ付けされたトークンに分割して、処理している値の種類を示す)と「パーサー」(レクサーからトークンの出力リストを取得する)そしてそれらを組み合わせて、抽象構文ツリーを形成しようとします)。 パーサーコンビネーターには、この区別はありません/必要ありません。通常、単純なパーサーは「レクサー」の作業を実行し、より高レベルのパーサーはこれらの単純なパーサーを呼び出して、作成するASTノードの種類を決定します。 質問 しかし、これらの違いを考えると(そしてこれはおそらく完全なものではありません!)、いつどれを使用するかについて知識のある選択をすることはできません。これらの違いの意味/結果が何であるかはわかりません。 パーサージェネレーターを使用すると、問題をより適切に解決できることを示す問題のプロパティは何ですか?Parser Combinatorを使用して問題を解決する方が適切であることを示す問題のプロパティは何ですか?

6
なぜレクサーを2Dアレイと巨大なスイッチとして実装するのですか?
私は学位を取得するためにゆっくりと取り組んでおり、この学期はCompilers 101です。DragonBookを使用しています。まもなくコースに入り、語彙分析と、決定論的有限オートマトン(以下、DFA)を介してそれを実装する方法について説明します。さまざまなレクサーの状態を設定し、それらの間の遷移を定義します。 しかし、教授と本は両方とも、巨大な2D配列(1つの次元としてのさまざまな非終端状態、および他の可能性のある入力シンボル)に相当する遷移テーブルと、すべての端子を処理するswitchステートメントを介して実装することを提案していますまた、非終端状態の場合は遷移テーブルにディスパッチします。 理論はすべて良好で優れていますが、実際にコードを何十年も書いた人として、実装は下手です。それはテスト可能ではなく、保守可能でもなく、読み取り可能でもなく、デバッグするのに苦労します。さらに悪いことに、その言語がUTFに対応していれば、どのように実用的であるかわかりません。非終端状態ごとに100万程度の遷移テーブルエントリがあると、急いで扱いにくくなります。 それで、取引は何ですか?主題に関する決定的な本が、このようにそれをするように言っているのはなぜですか? 関数呼び出しのオーバーヘッドは本当にそれほどですか?これはうまく機能するものですか、文法が事前にわからない場合に必要ですか(正規表現)?または、より具体的なソリューションがより具体的な文法でうまく機能する場合でも、すべてのケースを処理する何かでしょうか? (注:可能性のある重複「なぜ巨大なswitchステートメントの代わりにオブジェクト指向アプローチを使用するのか?」は近いですが、オブジェクト指向については気にしません。機能的アプローチ、またはスタンドアロン関数での賢明な命令型アプローチでも問題ありません。) また、例のために、識別子のみを持つ言語を考えてみましょう[a-zA-Z]+。これらの識別子はです。DFA実装では、次のようなものが得られます。 private enum State { Error = -1, Start = 0, IdentifierInProgress = 1, IdentifierDone = 2 } private static State[][] transition = new State[][]{ ///* Start */ new State[]{ State.Error, State.Error (repeat until 'A'), State.IdentifierInProgress, ... ///* IdentifierInProgress */ new State[]{ State.IdentifierDone, …

3
レクサーがそのパーサーに返すトークンのデータ型は何ですか?
タイトルで述べたように、レクサーはどのデータ型をパーサーに返す/与える必要がありますか?ウィキペディアが持っている字句解析の記事を読んだとき、それは次のように述べました: コンピュータサイエンスでは、字句解析とは、一連の文字(コンピュータプログラムやWebページなど)を一連のトークン(識別された「意味」を持つ文字列)に変換するプロセスです。 しかし、上記の声明と完全に矛盾して、別のサイトで質問した別の質問(好奇心があればコードレビュー)が回答されたとき、回答者は次のように述べました: 字句解析プログラムは通常、文字列を読み取り、これを語彙素のストリームに変換します。語彙素は数字のストリームである必要があります。 そして彼はこの視覚を与えました: nl_output => 256 output => 257 <string> => 258 後の記事で彼はFlex、既存のレクサーについて言及し、それを使って「ルール」を書くほうが、レクサーを手で書くよりも簡単だと言った。彼は私にこの例を与え始めました: Space [ \r\n\t] QuotedString "[^"]*" %% nl_output {return 256;} output {return 257;} {QuotedString} {return 258;} {Space} {/* Ignore */} . {error("Unmatched character");} %% 私の洞察を深め、より多くの情報を得るために、WikipediaのFlexに関する記事を読みました。Flexの記事では、トークンを使用して、次の方法で一連の構文規則を定義できることが示されました。 digit [0-9] letter [a-zA-Z] %% "+" { return PLUS; } "-" …
21 data-types  lexer  flex 

5
パーサーコンビネーターを使用して、構文解析と字句解析のパスを分けるのは良い習慣ですか?
パーサーコンビネーターを使用し始めたとき、私の最初の反応は、構文解析と字句解析の人為的な区別のように感じたものからの解放感でした。突然すべてが解析されただけです! しかし、私は最近、codereview.stackexchangeでこの区別を回復する誰かを示すこの投稿に出会いました。最初はこれは非常にばかげていると思いましたが、Parsecにはこの動作をサポートする機能が存在するという事実に疑問を抱きます。 パーサーコンビネーターで既にレキシシングされたストリームを解析することの利点/欠点は何ですか?

4
C ++でのレクサーの作成
C ++でレクサーを作成する方法に関する優れたリソース(書籍、チュートリアル、ドキュメント)は何ですか?優れたテクニックとプラクティスは何ですか? 私はインターネットを見ましたが、みんなlexのようなlexerジェネレーターを使うように言っています。私はそれをしたくありません。手で字句解析器を書きたいです。
18 c++  compiler  lexer 

5
レクサーのトークンを考え出す
私が作成したマークアップ言語のパーサーを書いています(Pythonで書いていますが、これはこの質問にはあまり関係ありません-実際、これが悪い考えのように思える場合は、より良いパスの提案が欲しいです) 。 私はここでパーサーについて読んでいます:http : //www.ferg.org/parsing/index.html、そして、私が正しく理解すれば、コンテンツをトークンに分割するべきレクサーの作成に取り組んでいます。理解できないのは、どのトークンタイプを使用するか、またはどのように作成するかです。たとえば、リンクした例のトークンタイプは次のとおりです。 ストリング 識別子 数 ホワイトスペース コメント EOF {や(などの多くの記号は、独自のトークンタイプとしてカウントされます 私が抱えている問題は、より一般的なトークンの種類が私にとって少しarbitrary意的であるように見えることです。たとえば、なぜSTRINGは独自のトークンタイプとIDENTIFIERであるのですか。文字列は、STRING_START +(IDENTIFIER | WHITESPACE)+ STRING_STARTとして表すことができます。 これは私の言語の難しさに関係しているかもしれません。たとえば、変数宣言はとして記述され{var-name var value}、でデプロイされ{var-name}ます。それはのように思える'{'し、'}'自分自身のトークンにする必要がありますが、VAR_NAMEとVAR_VALUE資格トークンタイプで、またはこれらの識別子の下で、両方の秋のでしょうか?さらに、VAR_VALUEには実際に空白を含めることができます。後の空白var-nameは、宣言内の値の開始を示すために使用されます。他の空白は値の一部です。この空白は独自のトークンになりますか?空白は、このコンテキストでのみその意味を持ちます。さらに、{変数宣言の始まりではないかもしれません..それはコンテキストに依存します(その言葉が再びあります!)。 {:名前宣言を開始し、{ 値の一部として使用することもできます。 私の言語は、ブロックがインデントで作成されるという点でPythonに似ています。Pythonがlexerを使用してINDENTおよびDEDENTトークンを作成する方法について読んでいました(多かれ少なかれ、他の多くの言語で何{をし、何を}するのか)。Pythonはコンテキストフリーであると主張しています。つまり、少なくとも字句解析者は、トークンの作成中にストリーム内のどこにいるかを気にする必要はありません。Pythonのレクサーは、前の文字を知らずに特定の長さのINDENTトークンを構築していることをどのように認識しますか(たとえば、前の行が改行だったので、INDENTのスペースの作成を開始します)。私もこれを知る必要があるので尋ねます。 私の最後の質問は最も愚かなものです。なぜレクサーが必要なのでしょうか?パーサーは文字ごとに行って、それがどこにあり、何を期待しているかを把握できるように思えます。レクサーは単純さの利点を追加しますか?
14 python  parsing  lexer 

1
文法に基づいてレクサーを作成するときに従う手順は何ですか?
文法、レクサー、パーサーに関する質問Clarificationに対する回答を読んでいると、答えは次のように述べています。 [...] BNF文法には、字句解析と構文解析に必要なすべてのルールが含まれています。 パーサーは文法に基づいているのに対し、これまでは常に字句解析は文法に基づいていないと考えていたため、これはやや奇妙に思えました。レクサーの作成に関する多数のブログ投稿を読んだ後、この結論に至りました。デザインの基礎として1つのEBNF / BNF を使用したことはありません。 パーサーと同様にレクサーがEBNF / BNF文法に基づいている場合、そのメソッドを使用してレクサーを作成するにはどうすればよいでしょうか?つまり、特定のEBNF / BNF文法を使用してレクサーを構築するにはどうすればよいですか? EBNF / BNFをガイドまたは設計図として使用してパーサーを記述することを扱った多くの投稿を見てきましたが、レクサーデザインと同等のことを示すものは今のところ見つかりませんでした。 たとえば、次の文法を取ります。 input = digit| string ; digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ; string = '"', { all characters - …

5
正規表現なしの字句解析
私はさまざまな上位レベルの言語(とりわけPython、PHP、Javascript)でいくつかのレクサーを調べてきましたが、それらはすべて何らかの形で正規表現を使用しているようです。正規表現がおそらくこれを行うための最良の方法であると確信していますが、正規表現なしで基本的な字句解析を達成する方法、おそらく何らかの直接文字列解析などがあるのか​​と思っていました。 ですから、どのような形でも正規表現を使用せずに、高水準言語*である種の基本的な字句解析を実装することは可能ですか? * Perl / PHP / Python / Javascriptなどの高レベル言語。Cでそれを行う方法は確かにあります

3
文法、レクサー、パーサーに関する説明
背景情報(5月スキップ):提供されているDSLの文法を設計する必要があるuniで設定されたタスクに取り組んでいます。文法はBNFまたはEBNFでなければなりません。他にも、文法の語彙ルールと構文解析ルールについて評価されています。たとえば、ルールが言語サブセットに適しているかどうか、これらのルールがどれほど包括的であるか、ルールがどれほど明確であるかなどです。 私が理解していないのは、これらのルールがBNFで定義された文法でカバーされているかどうかです(これは私たちにとって新しいトピックです)。 質問:BNFまたはEBNFのいずれかで定義されている特定の言語の文法には、字句解析 または構文解析、あるいはその両方のルールが含まれていますか?(またはこれらは他の場所で指定する必要がありますか?) また、何が字句規則と考えられますか?そして、何が解析ルールと考えられますか?
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.