Upgrade to Pro — share decks privately, control downloads, hide ads and more …

オートマトンと字句解析でRoslynを読む

 オートマトンと字句解析でRoslynを読む

オートマトンと字句解析でRoslynを読む
.NETラボ 勉強会 2026年7月
https://dotnetlab.connpass.com/event/393450/

Avatar for tomokusaba

tomokusaba

July 24, 2026

More Decks by tomokusaba

Other Decks in Technology

Transcript

  1. 自己紹介 • 2022/08-2027 Microsoft MVP (Microsoft Azure, Developer Technologies) •

    tomo_kusaba • ドラクエ大好き ドラクエ10のプレイ時間→ 1キャラ目:2691時間 2キャラ目:919時間 3キャラ目:793時間 4キャラ目:190時間(配信用)
  2. オートマトンについて • DFA(Deterministic Finite Automaton決定性有限オート マトン)は現在の状態と入力によって次の状態が決定できる機械 • NFA(Nondeterministic Finite Automaton非決定性有限

    オートマトン)は次の状態が複数あり得る機械 • 履歴をすべて持たない • DFAが有限であるとは入力文字列をまるごと記憶しない • 記憶するのは現在の状態だけ
  3. 集合とオートマトン • 一般的に有限オートマトンは以下のような形式で表されます (Q, Σ,δ, q0, F) 記号 意味 詳細

    Q 状態 状態列の許可値集合 Σ 入力記号集合 入力し得るイベントの集合 δ 遷移関数 許可遷移表 q0 開始状態 初期状態の定義 F 受理状態集合 終端の定義
  4. DFAについて 状態 意味 できること 0円 まだ投入なし 50円または100円入れる 50円 50円投入済み さらに50円または100円入れる

    購入可能 100円以上 商品を出す Start 100円 0円 50円 50円 50円 購入可能 100円 商品を出す End
  5. 字句解析器(Lexer) • ソースコードの文字列をトークンに分解する処理 var answer = 3 + 4; トークン文字列

    トークン種類 説明 var Identifier Token 文脈キーワードとして解釈され得る識別子 answer Identifier 識別子 = EqualsToken 代入演算子 3 NumericLiteralToken 数値リテラル + PlusToken 加算演算子 4 NumericLeteralToken 数値リテラル ; SemicolonToken 文の区切り
  6. オートマトンを字句解析器に当てはめる 記号 意味 字句解析 Q 状態 トークン種類(Identifier, Equals, Semicolon) Σ

    入力記号集合 テキスト文字列 δ 遷移関数 トークンからどのトークンへ遷移可能かの許可表 q0 開始状態 F 受理状態集合 (EndOffFileToken)
  7. Roslynとオートマトンとの用語対比 用語 意味 記号 Roslynでみる例 SourceText ソースコード全体の文字列を表す入力 Σ CSharpSyntaxTree.ParseText(Sour ceText)

    lexeme 分類前の入力から切り出した文字列 token lexemeに種類をつけたもの SyntaxKind token,node,triviaの種類を表す SyntaxKind.PlusToken SyntaxToken 構文木の中にあるtokenの公開API表現 token.Kind(), token.Text SyntaxTrivia 空白、改行、コメントのように構文の外側につく情 報 WhitespaceTrivia, SingleLineCommentTrivia SyntaxNode tokenを組み合わせた構文上のまとまり LocalDeclarationStatementSyntax Diagnostic エラーや警告など解析中に見つかった問題 token.GetDiagnostics() green tree 親や位置を持たない内部表現の構文木 InternalSyntax 側の node / token red tree 親・位置・SyntaxTreeへの参照を持つ公開API 側の構文木 GetRoot() で触る node / token answer, 40, + Q IdentifierToken, NumericLiteralToken
  8. ParseTextからLexerへ 行 意味 new InternalSyntax.Lexer(...) 文字列をtokenに分ける字句解析器を作る new InternalSyntax.Language Parser(...) token

    を受け取り、文・式・宣言などの構文に組み立てる parser を 作る ParseCompilationUnit() C# ファイル全体を表す構文木の根を作る CreateRed() 内部表現から、公開 API として辿れる red tree を作る
  9. Lexer 読む順番 メソッド 内容 1 Lex 現在の LexerMode に応じて、通常 token・directive・XML

    doc comment などの読み方を選ぶ 2 LexSyntaxToken leading trivia、token 本体、trailing trivia をまとめて 1 つの SyntaxToken にする 3 ScanSyntaxToken 現在の文字を見て SyntaxKind を決める 4 ScanIdentifierOrKeyword 識別子・キーワード候補を読む。内部で ScanIdentifier などに進 む 5 Create TokenInfo から SyntaxFactory で実際の token を作る
  10. ScanSyntaxToken • 最長一致の考えでTokenを選ぶ a++ + b 入力位置 読み方 token a

    識別子として読む IdentifierToken ++ 2 文字をまとめて読む PlusPlusToken + 空白のあと、1 文字の演算子とし て読む PlusToken b 識別子として読む IdentifierToken
  11. TokenInfoからSyntaxTokenへ • Tokenの種類ごとに必要情報を集めてくる Tokenの種類 必要情報 例 識別子 表面上の文字列、値としての文字列、 contextual keyword

    var, answer 数値リテラル 表面上の文字列、数値としての値、型の候補 40, 0x10 文字リテラル 引用符やエスケープを含む文字列 "¥¥n" 記号Token ほぼ、SyntaxKindだけで足りる +, =, ;
  12. オートマトンとRoslyn Lexerでの姿 オートマトン理論 Roslyn Lexer での姿 状態 LexerMode、TextWindow.Position、読み取り中の token 種別

    入力記号 現在位置の char、または Unicode エスケープを解釈した文字 遷移関数 ScanSyntaxToken や ScanIdentifier の分岐 受理状態 TokenInfo.Kind が決まり、token の終端に到達した状態 受理ラベル SyntaxKind.IdentifierToken など 出力 SyntaxFactory が作る SyntaxToken
  13. まとめ 理論 コンパイラー Roslyn 集合 数字、英字、空白、記号の分類 char の判定、Lexer 内の分岐 関係

    / 関数 (状態, 入力) -> 次の状態 トークンを読むための状態遷移 言語 受け入れたい文字列の集合 識別子、数値、文字列などのトー クンパターン DFA / NFA 入力を読み進める有限状態機械 ScanSyntaxToken などの分 岐を DFA 的に眺める トークン 字句解析の出力 SyntaxKind.IdentifierToke n など 構文木 トークンを構文に組み立てたモデル CSharpSyntaxTree.ParseT ext と CompilationUnitSyntax