コンパイラの字句解析は有限オートマトン(有限オートマトン)と正規表現(正規表現)に基づいています。
アルファベット: 有限の記号セット アルファベット: 有限記号のコレクション 文字列
: 指定されたアルファベットからの記号のシーケンス 文字列: 指定のアルファベットからの記号のシーケンス 言語
: 文字列のセット 文字列の集合
たとえば、x12 = 32; トークンがあります
x12 識別子
= 割り当て
32 unsigned int
; ステートメントの終わり
ここでの 4 つのトークンは実際には 4 つの言語とみなすことができ、各言語には独自の文字構成があります。
文字列 (またはトークン) を有限オートマトンまたは正規表現に渡すと、これが正当なトークンであるか、その言語に属するトークンではないことが返されます。
有限オートマトンと言語を識別するツールとしての正規表現は正規言語(標準言語)しか認識できません
DFA は比較的厳密で、考えられるすべての出力には 1 つのみの出力があります。
L = {w | w には部分文字列として 101 が含まれます}
DFA (決定論的有限オートマトン) (決定論的有限オートマトン) L 用
DFA の遷移テーブル:
コード
switch(state)
case q0:
if sym == 0 go to q0
if sym == 1 go to q1
case q1:
if sym == 0 go to q1
if sym == 1 go to q2
すべての DFA は NFA でもありますが、すべての NFA が DFA であるわけではありません
NFA (非決定的有限オートマトン) (非決定的有限オートマトン) L 用
NFAの遷移表
NFA to DFA 方式: サブセット構築サブセット構築方式
コードで実装する場合、DFA と NFA のどちらが実装しやすいのでしょうか?
答えは DFA です。通常、字句解析のプロセスで DFA が構築されます。
L = {w | w には部分文字列 101 または部分文字列 111 が含まれます}
NFA:
L = {w | w には部分文字列 101 が含まれるか、部分文字列 111 で終わります。}
NFA:
正規表現 (正規表現)
Thompson の 構築: 正規表現を NFA に変換する方法
NFA から DFA へ: サブセット構築 サブセット構築方法
正規表現は私たち人間にとって最も理解しやすい方法です。まず正規表現を NFA に変換し、次にサブセット構築方法を通じて最終的な DFA に変換する必要があります。DFA に変換して初めて、直感的にコードを書くことができます
。
これらの変換を行うのに役立つ flex というツールがあり、正規表現を入力するだけで、ツールは C 言語コードを返します。
L = { w | w は部分文字列として 101 を含む} の正規表現は次のとおりです。
(0 U 1)* 101 (0 U 1)*
または ∑* 101 ∑* と書くこともできます //ここで ∑* はすべての可能な入力を表します
正規表現の例をさらに 2 つ示します。
L = {w | w は偶数の長さ} // 偶数の長さ
(∑∑)*
L = {w | w の長さは奇数です} //長さは奇数です
∑(∑∑)*
unsigned int の正規表現
: [0 - 9]* 先頭に 0 を許可し、空の文字列を許可します
0 U [1 - 9][0 - 9]* 先頭に 0 を許可しません
0 U [1 - 9][0 - 9]* 的NFA:
変数の命名規則とその正規表現 (_ U [a - z]) ([az] U [0 - 9] U _)*その NFA
: