web-dev-qa-db-ja.com

レクサーは複数行のステートメント(例:関数の定義、Control-Flowステートメント)をどのように処理する必要がありますか?

tl; dr-ers:

レクサーは通常、非インラインステートメントをどのように処理しますか。指定されたステートメント区切り文字で終了しないステートメント。制御フローステートメントなど?


私は字句解析をかなりよく理解していると思います。レクサー/パーサーを理解するための探求に進むことができます。ただし、レクサーの処理方法は理解しています 1複数行のステートメント。

プログラミング言語構文の比較 に関するWikipediaの記事を読んだ後、すべての言語に共通していることは、非常に特殊なステートメント区切りがあることです。セミコロン(;)をステートメントの区切り文字として使用するものもあれば、空白(\ws)を使用するものもあれば、ピリオド(.)を使用するものもあります。

この方法を使用すると、これらのプログラミング言語が複数の行にまたがるfunctions\class\controlフローを持つ方法を確認できません。私が間違っている場合は修正してください。ただし、ほとんどの一般的なプログラミング言語(Python、Java、C、C++、C#、Javascriptなど)は、関数の最後にステートメント区切り文字を使用しないでください。 、またはクラス(C++のクラスはそこにセミコロンを使用することを知っていますが、それはポイントのほかにです)、または制御フローです。

これは、次のいずれかを意味します。A:レクサーは、複数行にわたるステートメントに対して特別な例外を作成します。またはB:字句解析プログラムは複数行のステートメントを通常のステートメントとして扱うだけであり、それらを理解するのはパーサーの仕事です。

たとえば、次の擬似プログラムをC++で取り上げます。

int exampleVar; //<-- inline statement. Delimited with a semicolon

void exampleFunc() { //<-- multi-line statement. This statement is the start of a block.
    // do things
} //<-- this is where the statement that was started above, should end?

明らかに、最初のステートメントをどこで終了すればよいかは簡単にわかります。セミコロンで終わります。しかし、2番目のステートメントはどのように扱われますか?ステートメントは、閉じ中括弧までのすべてを含むように拡張されていますか?

または、私は自分の考えで誤って見過ごされる可能性もあります。レクサーは絶対に何の関係もないかもしれません 1複数行のステートメント。これはパーサーの仕事ですか?つまり、意味を理解するのはパーサーの仕事ですか 1複数行のステートメント?

可能な限り明確にするために、私の質問は次のとおりです。どのように(そもそもそれらが必要な場合)、レクサーがインラインではなく、まるでそれらがあるかのように終了できないステートメントを処理する必要があります。レクサーは通常、非インラインステートメントをどのように処理しますか。指定されたステートメント区切り文字で終了しないステートメント。制御フローステートメントなど?

1明確にするために、行を継続するという意味で、複数行のステートメントを意味するわけではありません。ブロックから始まるステートメントの意味でそれらを意味します。関数宣言など。関数を定義するときは、特定のブロック区切り文字までの関数定義に続くステートメントも知っておく必要があります。したがって、定義の後にステートメントを単に終了させることはできません。

5
Christian Dean

すでに推測したように、これはレクサーの仕事ではありません。ステートメント、宣言、定義の面では取引されませんが、tokensと呼ばれるより低レベルのエンティティで取引されます。

たとえば、次のC関数の場合、

static int
sum_plus_42(const int a, const int b)
{
  int result = a + b + 42;
  return result;
}

レクサーは次のトークンのシーケンスを生成します。

  • キーワードstatic
  • キーワードint
  • 識別子sum_plus_42
  • 左括弧
  • キーワードconst
  • キーワードint
  • 識別子a
  • コンマ
  • キーワードconst
  • キーワードint
  • 識別子b
  • 右括弧
  • 開きブレース
  • キーワードint
  • 識別子result
  • 演算子=
  • 識別子a
  • 演算子+
  • 識別子b
  • 演算子+
  • 整数リテラル42
  • セミコロン
  • キーワードreturn
  • 識別子result
  • セミコロン
  • 右括弧

コード内に構文エラーがあった場合(括弧の不一致など)、レクサーはとにかく喜んでトークン化します。ただし、数値リテラル内の無効な文字などの字句エラーを検出します(123wrong456など)。

ソースコードがトークン化された後、パーサーはトークンシーケンスから構文ツリーを構築します。

字句解析と構文解析はどちらも、正式な文法の仕様に基づいて行われ、これらを1つに統合できなかった理論的な理由はありません。ただし、実際には、2つのステップを分離することにより、よりクリーンで優れた構造化コードが作成されます。字句解析の文法は通常、はるかに単純でregularですが、言語の構文を記述するために使用される文法はcontext-freeです。実際には、文法はそれほどクリーンではないことが多く、通常の文脈自由文法の正式な規則の外に多かれ少なかれ特殊なケースがあります。

これが明確でない場合、構文解析の文法で使用される終端記号は、レクサーによって生成されるトークンであり、これは非終端です。 =独自の文法の記号。

7
5gon12eder