banner
沈青川

旧巷馆子

愿我如长风,渡君行万里。
twitter
jike

🍮 プロジェクトコンパイルの実践的なデザートを試してみましょう · テンプレート文字列ノードの構築方法は?

👓 レキシカル解析と構文解析#

この記事では、私が長い時間をかけて理解した知識を簡単にまとめるだけなので、詳しく説明することはありません。ただ、読者の理解を助けるために、これらのトピックについて少し深く話すことがあります。

レキシカルアナライザ(英語では Lexer または Scanner と呼ばれることが一般的です)は、ソースコードを「トークン」と呼ばれる不可分の要素のリストに分割するために使用されます。

C 言語の例を挙げて説明します。

#include <stdio.h>

int main() {
  printf("Hello world!");
}

上記のソースコードに含まれるすべてのトークンは次のとおりです。

<プリプロセッサディレクティブ #include> <スペース> <左尖括弧 '<'> <名前 stdio.h> <右尖括弧 '>'> <改行>
<改行>
<キーワード int> <スペース> <名前 main> <左丸括弧 '('> <右丸括弧 ')'> <スペース> <左波括弧 '{'> <改行>
<スペース> <スペース> <名前 printf> <左丸括弧 '('> <文字列リテラル> <右丸括弧 ')'> <セミコロン ';' > <改行>
<右波括弧 '}'>

レキシカルアナライザの入力は文字列であり、出力はトークンのリストです。各トークンには、位置(Position)内容(Raw content)、** タイプ(Token Type)** の 3 つの重要な属性があります。位置を記録することは、後でコードにエラーがあった場合に問題を特定するのに役立ちます。

構文解析器(英語では Parser と呼ばれることが一般的です)は、プログラミング言語の設計仕様に基づいて、定義に合致する複数のトークンを組み合わせて構文ノードを作成し、最終的に「抽象構文木」(AST、Abstract Syntax Tree)を作成する作業です。

🥵 テンプレート文字列の処理の難しさ#

以下では、JavaScript のテンプレート文字列構文を例に説明します。

レキサーの実装を始めたとき、入力内容を一つずつ読み取るだけで、対応するトークンを取得できると思っていましたが、テンプレート文字列の場合は異なることに気づきました。

テンプレート文字列をレキシカル解析の段階で「分割できない」トークンとして読み取るのは非常に困難です。明らかに、テンプレート文字列は分割可能です。

`my name is ${"David" + ` - ${firstName}`}, nice to meet you!`

🤔️ どうすればいいですか?#

トークンを順番に読み取るためには、解析の現在の状態を示すいくつかの変数を設定し、通常の文字列解析と同じ方法でテンプレート文字列を処理しないようにする必要があります。

確かなことは、テンプレート文字列の処理は構文解析の段階で行われることであり、次の 2 つの種類の構文ノードを含むことです。

  • 分散した複数の文字列テキスト
  • 挿入式(式)、挿入式も構文ノードです
interface TemplateStringNode {
  quasis: TemplateElement[]
  expressions: ExpressionNode[]
}

したがって、最も良い方法は、パーサーにテンプレート文字列の解析を開始するための特定のトークンを見つけ、状態情報に基づいて可能なネストの処理を行うことです。

次の 2 つの重要な情報を設定します。

  1. isReadingText:テキストを読み取る必要があるかどうか
  2. nested:ネストの深さ

image

上記の図の推論分析に従って、次の結論に達することができます。

  1. テンプレート文字列の引用符isReadingTextの状態を反転させます
  2. 挿入式の開始マーカー${nestedを 1 つ増やし、isReadingTextfalseに設定します。なぜなら、読み取るのは挿入式だからです。
  3. 右波括弧nestedを 1 つ減らし、isReadingTexttrueに設定します。なぜなら、テンプレート文字列のテキストの読み取りに戻ったからです。

isReadingTextfalseに設定され、nested のレベルが 0 になるまで、テンプレート文字列ノードの解析は終了しません。

参考文献#

以下の 2 つの Stackoverflow の質問に参考になる情報があります:

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。