Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
Wasmで動くRust製マーク ダウンパーサーを自作した話 0Yu 隅田川.dev
Slide 2
Slide 2 text
0yu(おゆ,ぜろゆー) 好きな技術 ● Webフロントエンド、Rust 趣味 ● 映画鑑賞・旅行・ゲーム etc ● 最近はハイラルの勇者をしています 自己紹介 っっっz yud0uhu 2
Slide 3
Slide 3 text
● Rustと言語処理系の勉強のため、簡易的なマークダウンパーサーを スクラッチで実装した ● 生成したWASMをNuxt3+Viteの環境で動かした はじめに
Slide 4
Slide 4 text
字句解析 ● テキストを字句の列(トークン)に分解する こと ● 字句解析を行うプログラムを字句解析器 (lexerまたはtokenizer)と呼ぶ 言語処理系の概要
Slide 5
Slide 5 text
構文解析 ● トークン列を抽象構文木(abstract syntax treeまたはAST)に変換する ● 抽象構文木とは、言語の構文を解釈し、 データ構造を取り出した(抽象化した)木構 造のこと 言語処理系の概要
Slide 6
Slide 6 text
意味解析 ● 構文木の意味を解析する ● コンパイラでは、この段階で中間コード を生成する 言語処理系の概要
Slide 7
Slide 7 text
最適化 ● 中間コードを変形して、効率のよいプロ グラムに変換すること ● コンパイラでは、パースしたソースコー ドから無駄な処理を分析し、コード最適 化を行う 言語処理系の概要
Slide 8
Slide 8 text
コード生成 ● 抽象構文木を入力とし、ターゲットとな る言語のコードを生成する ● コンパイラでは、この段階で中間コード をネイティブコード(ターゲットのCPUが 解釈できる実行形式のバイナリコード)に 変換する 言語処理系の概要
Slide 9
Slide 9 text
マークダウンテキストを入力とし トークンに分割(字句解析) →ASTに変換(構文解析) →HTMLを生成(コード生成) できるようにする パーサーの構成
Slide 10
Slide 10 text
● 字句の列(トークン)を定義する ● 入力されたテキストをトークンに分割する 字句解析器(Lexer)の実装
Slide 11
Slide 11 text
実装するマークダウンタグ ● 見出し(
~
) ● 太字(
) ● 斜体(
) ● 引用() ● リスト(
,
) 字句解析器(Lexer)の実装
Slide 12
Slide 12 text
トークンを定義する ● Heading,Bold,Italic,BlockQu otes,Lists の5つのトークン を定義する 字句解析器(Lexer)の実装
Slide 13
Slide 13 text
字句解析(Tokenize)する ● 字句解析は関数lexが担う ● 字句解析のための文字列操作 はイテレータで行う ○ イテレータとは、複数個 の要素の集まり(配列・リ ストなど)から、次の要素 を一つずつ順に取り出す インターフェースのこと 字句解析器(Lexer)の実装
Slide 14
Slide 14 text
fn next(&mut self) -> Option ● nextはイテレータを消費するメソッド ● 呼び出されるたびにイテレータを消費してSome に包まれた一要素を 返し、繰り返しが終わるとNoneを返す ○ next()で入力された文字列を一つずつ取り出し、変数cに格納す る 字句解析器(Lexer)の実装
Slide 15
Slide 15 text
● 見出しタグの判定では、頭文字が#と (半角スペース)で始まる語句を 識別できるようにしたい ● 変数cが#、in_boldがfalse(太字ではない)でin_italicがfalse(斜体で はない)のときにのみ処理するようなパターンマッチングを書く 字句解析器(Lexer)の実装
Slide 16
Slide 16 text
● peekはイテレータを消費する前に、前もって参照を返す(新たなイテ レータPeekableを返す)メソッド ● 行頭に#が連続して出現する時(chars.peek()とSome(&'#')が等しい 時)、一文字ずつ文字列を読み進めながら、levelを1ずつ加算 字句解析器(Lexer)の実装
Slide 17
Slide 17 text
● peekはイテレータを消費する前に、前もって参照を返す(新たなイテ レータPeekableを返す)メソッド ● 行頭に#が連続して出現する時(chars.peek()とSome(&'#')が等しい 時)、一文字ずつ文字列を読み進めながら、levelを1ずつ加算 字句解析器(Lexer)の実装
Slide 18
Slide 18 text
● levelの値に応じて見出しのレベルを判定 ● 適切なToken::Headingをtokensに追加し、見出しをトークン化 字句解析器(Lexer)の実装
Slide 19
Slide 19 text
● 半角スペースの後に続くテキストがTokenの値に正しく解釈されるよ うにしたい ● 現在の文字が半角スペースのときにのみ、charsから文字を取り出す 処理を書く 字句解析器(Lexer)の実装
Slide 20
Slide 20 text
● トークンから抽象構文木(AST)を構築する ● ASTはノードが集まってできた木構造 ○ Heading(見出し)タグは、Heading Level(見出しレベル)ノード とText(文字列)ノードが集まってASTを構築する 構文解析器(Parser)の実装
Slide 21
Slide 21 text
● トークン配列からASTNodeを構築 構文解析器(Parser)の実装
Slide 22
Slide 22 text
● Token::Headingをパースして、AstNode::Headingに変換 構文解析器(Parser)の実装
Slide 23
Slide 23 text
● 構築されたASTをHTMLに変換する ○ AstNode型のスライスを参照するast: &[AstNode]を引数に持 ち、Stringを返す関数generate_htmlを定義 コード生成器(Generator)の実装
Slide 24
Slide 24 text
● パターンマッチング→ASTのノードをhtmlタグにフォーマットし、 result配列に追加する処理を愚直に書く コード生成器(Generator)の実装
Slide 25
Slide 25 text
● 関連関数text_to_tokenで呼び出す レンダリング
Slide 26
Slide 26 text
● wasm-packでビルドする ○ Cargo.tomlで環境設定を行う WASMの生成
Slide 27
Slide 27 text
● lib.rsに#[wasm_bindgen]アトリビュートを付与 WASMの生成
Slide 28
Slide 28 text
● % rustup target add wasm32-unknown-unknownでターゲット アーキテクチャを追加して% wasm-pack buildする ● target/wasm32-unknown-unknown/release に、最適化されたビ ルドバイナリが出力される WASMの生成