Aho UllmanとSethiによるコンパイラの構築では、ソースプログラムの文字の入力文字列は、論理的な意味を持つ文字のシーケンスに分割され、トークンと呼ばれ、語彙素はトークンを構成するシーケンスであるとされています。基本的な違いは何ですか?
Aho UllmanとSethiによるコンパイラの構築では、ソースプログラムの文字の入力文字列は、論理的な意味を持つ文字のシーケンスに分割され、トークンと呼ばれ、語彙素はトークンを構成するシーケンスであるとされています。基本的な違いは何ですか?
回答:
「CompilersPrinciples、Techniques、&Tools、2nd Ed。」(WorldCat)を使用して、Aho、Lam、Sethi、Ullman、別名The Purple Dragon Book、
語彙素pg。111
語彙素は、トークンのパターンに一致するソースプログラム内の文字のシーケンスであり、字句解析プログラムによってそのトークンのインスタンスとして識別されます。
トークンページ 111
トークンは、トークン名とオプションの属性値で構成されるペアです。トークン名は、特定のキーワードや識別子を示す入力文字のシーケンスなど、一種の語彙単位を表す抽象的な記号です。トークン名は、パーサーが処理する入力シンボルです。
パターンページ 111
パターンは、トークンの語彙素がとることができる形式の説明です。トークンとしてのキーワードの場合、パターンはキーワードを形成する文字のシーケンスです。識別子やその他のトークンの場合、パターンはより複雑な構造であり、多くの文字列と一致します。
図3.2:トークンの例pg.112
[Token] [Informal Description] [Sample Lexemes]
if characters i, f if
else characters e, l, s, e else
comparison < or > or <= or >= or == or != <=, !=
id letter followed by letters and digits pi, score, D2
number any numeric constant 3.14159, 0, 6.02e23
literal anything but ", surrounded by "'s "core dumped"
レクサーとパーサーとのこの関係をよりよく理解するために、パーサーから始めて、入力に逆戻りします。
パーサーの設計を容易にするために、パーサーは入力を直接処理するのではなく、レクサーによって生成されたトークンのリストを取り込みます。我々のようなトークンを参照して、図3.2におけるトークンの列を見るとif
、else
、comparison
、id
、number
とliteral
。これらはトークンの名前です。通常、レクサー/パーサーの場合、トークンは、トークンの名前だけでなく、トークンを構成する文字/記号、およびトークンを構成する文字列の開始位置と終了位置を保持する構造です。エラー報告、強調表示などに使用される開始位置と終了位置。
これで、レクサーは文字/記号の入力を受け取り、レクサーのルールを使用して、入力された文字/記号をトークンに変換します。現在、レクサー/パーサーを使用する人々は、頻繁に使用するものに対して独自の言葉を持っています。トークンを構成する一連の文字/記号として考えるのは、レクサー/パーサーを使用する人々が語彙素と呼ぶものです。したがって、語彙素を見るときは、トークンを表す文字/記号のシーケンスを考えてみてください。比較例では、文字/記号のシーケンスは、<
or>
またはelse
orなどの異なるパターンにすることができます3.14
。
2つの関係を考える別の方法は、トークンは、入力からの文字/記号を保持する語彙素と呼ばれるプロパティを持つパーサーによって使用されるプログラミング構造であるということです。ここで、コード内のトークンのほとんどの定義を見ると、トークンのプロパティの1つとして語彙素が表示されない場合があります。これは、トークンがトークンと語彙素を表す文字/記号の開始位置と終了位置を保持する可能性が高いためです。入力が静的であるため、必要に応じて文字/記号のシーケンスを開始位置と終了位置から導出できます。
can you please explain by taking simple input at parser stage and when does parser asks for tokens from lexer.
はディスカッションサイトではありません。それは新しい質問であり、新しい質問として尋ねる必要があります。
ソースプログラムが字句解析プログラムに入力されると、文字を語彙素のシーケンスに分割することから始まります。次に、語彙素はトークンの構築に使用され、語彙素はトークンにマップされます。myVarという変数は、< id、 "num">を示すトークンにマップされます。ここで、 "num"は、シンボルテーブル内の変数の場所を指している必要があります。
簡単に言えば:
例は次のとおりです
。x= a + b * 2
語彙素を生成します:{x、=、a、+、b、*、2}
対応するトークン:{< id、0>、<=>、< id、1 >、<+>、< id、2>、<*>、< id、3>}
LEXEME-トークンを形成するPATTERNと一致する文字のシーケンス
PATTERN-トークンを定義する一連のルール
TOKEN-プログラミング言語の文字セットに対する意味のある文字のコレクション例:ID、定数、キーワード、演算子、句読点、リテラル文字列
語彙素-語彙素は、トークンのパターンに一致するソースプログラム内の文字のシーケンスであり、字句解析プログラムによってそのトークンのインスタンスとして識別されます。
トークン-トークンは、トークン名とオプションのトークン値で構成されるペアです。トークン名は語彙単位のカテゴリです。一般的なトークン名は次のとおりです。
プログラミング言語Cでこの式を考えてみましょう。
合計= 3 + 2;
トークン化され、次の表で表されます。
Lexeme Token category
------------------------------
sum | Identifier
= | Assignment operator
3 | Integer literal
+ | Addition operator
2 | Integer literal
; | End of statement
字句アナライザー(スキャナーとも呼ばれます)の動作を見てみましょう
式の例を見てみましょう:
INPUT : cout << 3+2+3;
FORMATTING PERFORMED BY SCANNER : {cout}|space|{<<}|space|{3}{+}{2}{+}{3}{;}
ただし、実際の出力ではありません。
スキャナーは、入力がなくなるまで、ソースプログラムテキストの語彙素を繰り返し探します。
語彙素は、文法に存在する有効な端末の文字列を形成する入力の部分文字列です。すべての語彙素は、最後に説明されているパターンに従います(読者が最後にスキップする可能性のある部分)
(重要なルールは、次の空白が検出されるまで、有効な端末の文字列を形成する可能な限り長いプレフィックスを探すことです...以下で説明します)
語彙素:
(「<」も有効な端末文字列ですが、上記のルールでは、スキャナーから返されるトークンを生成するために、語彙素「<<」のパターンを選択する必要があります)
トークン:スキャナーが(有効な)語彙素を見つけるたびに、トークンは一度に1つずつ返されます(パーサーから要求された場合はスキャナーによって)。スキャナーは、まだ存在しない場合は、語彙素を見つけると、トークンを生成するために、シンボルテーブルエントリ(属性:主にトークンカテゴリとその他のいくつか)を作成します。
「#」はシンボルテーブルエントリを示します。わかりやすくするために上記のリストの語彙素番号を指摘しましたが、技術的にはシンボルテーブルの実際のレコードのインデックスである必要があります。
次のトークンは、上記の例で指定された順序でスキャナーからパーサーに返されます。
<識別子、#1>
<オペレーター、#2>
<リテラル、#3>
<オペレーター、#4>
<リテラル、#5>
<オペレーター、#4>
<リテラル、#3>
<パンクチュエーター、#6>
違いがわかるように、トークンは、入力の部分文字列である語彙素とは異なり、ペアです。
そして、ペアの最初の要素はトークンクラス/カテゴリです
トークンクラスは以下のとおりです。
そしてもう1つ、スキャナーは空白を検出し、それらを無視し、空白のトークンをまったく形成しません。すべての区切り文字が空白であるわけではありません。空白は、スキャナーがその目的で使用する区切り文字の1つの形式です。入力内のタブ、改行、スペース、エスケープ文字はすべて、まとめて空白区切り文字と呼ばれます。他の区切り文字はほとんどありません ';' '、' ':'など。トークンを形成する語彙素として広く認識されています。
ここで返されるトークンの総数は8ですが、語彙素に対して作成されるシンボルテーブルエントリは6つだけです。語彙素も合計8つです(語彙素の定義を参照)
---この部分はスキップできます
A ***pattern*** is a rule ( say, a regular expression ) that is used to check if a string-of-terminals is valid or not
。
If a substring of input composed only of grammar terminals is
following the rule specified by any of the listed patterns , it is
validated as a lexeme and selected pattern will identify the category
of lexeme, else a lexical error is reported due to either (i) not
following any of the rules or (ii) input consists of a bad
terminal-character not present in grammar itself.
for example :
1. No Pattern Exists : In C++ , "99Id_Var" is grammar-supported string-of-terminals but is not recognised by any of patterns hence lexical error is reported .
2. Bad Input Character : $,@,unicode characters may not be supported as a valid character in few programming languages.`
語彙 素語彙素は、トークン内の一連の文字(英数字)であると言われています。
トークン トークンは、単一の論理エンティティとして識別できる文字のシーケンスです。通常、トークンはキーワード、識別子、定数、文字列、句読記号、演算子です。数字。
パターンパターン と呼ばれるルールによって記述された文字列のセット。パターンは、トークンになり得るものを説明し、これらのパターンは、トークンに関連付けられた正規表現によって定義されます。
字句解析プログラムは、文字のシーケンスを取得して、正規表現に一致する語彙素を識別し、さらにそれをトークンに分類します。したがって、語彙素は一致する文字列であり、トークン名はその語彙素のカテゴリです。
たとえば、入力が「int foo、bar;」の識別子の以下の正規表現について考えてみます。
文字(文字|数字| _)*
ここでは、foo
およびbar
ので、両方の語彙素であるが、1つのトークンとして分類された正規表現に一致するID
、すなわち識別子。
また、次のフェーズ、つまり構文アナライザーは、語彙素ではなくトークンについて知る必要があることに注意してください。
語彙素は基本的にトークンの単位であり、基本的にトークンに一致する文字のシーケンスであり、ソースコードをトークンに分割するのに役立ちます。
例:ソースがある場合はx=b
、その語彙素は次のようになりx
、=
、b
およびトークンは次のようになり<id, 0>
、<=>
、<id, 1>
。