私が作成したマークアップ言語のパーサーを書いています(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のスペースの作成を開始します)。私もこれを知る必要があるので尋ねます。
私の最後の質問は最も愚かなものです。なぜレクサーが必要なのでしょうか?パーサーは文字ごとに行って、それがどこにあり、何を期待しているかを把握できるように思えます。レクサーは単純さの利点を追加しますか?