🗓️

Rustでインタプリタを作ってみる(日記): 2日目

2022/02/24に公開

達成すること

  • 構文解析を理解、実装の一歩を書く
  • lexer.rs, token.rsを作る
  • 最終Output
   {Type:let Literal:let}
   {Type:IDENT Literal:add}
   {Type:= Literal:=}
   {Type:fn Literal:fn}
   {Type:( Literal:(}
   {Type:IDENT Literal:x}
   {Type:, Literal:,}
   {Type:IDENT Literal:y}
   {Type:) Literal:)}
   {Type:{ Literal:{}
   {Type:IDENT Literal:x}
   {Type:+ Literal:+}
   {Type:IDENT Literal:y}
   {Type:; Literal:;}
   {Type:} Literal:}}
   {Type:; Literal:;} 

アウトプット

文字列を受け取る→字句を定義→定義した字句に分解、スペース処理

https://mermaid-js.github.io/mermaid/#/classDiagram

  • 設計図

  • 文字、数字、など自由な入力を字句ごとに分けたあとなんのタイプ;kindか判定する関数を作る必要がある。

    • { } ; : ( ) , etc などは決まった形だからnexttoken()内で簡単にmatch処理していいが、それ以外の自由な入力が。。。という話
  • isLetter()&readLetter()

  • isNumber()& readNumber()

--- 最後の処理

read eval print loop : REPL

fn Start {

// scan input

lexer::new()

while tokenkind == EOF{

printf(token)

}

}

  • 変更点

Start()はlexer::newするのでlexerクラス内のメソッドにすべきではない。

repl.rsを作った。

https://doc.rust-lang.org/reference/tokens.html#ascii-escapes

http://www3.nit.ac.jp/~tamura/ex2/ascii.html

↑ASCII表など

最終結果

疑問

設計の疑問点

struct Lexerにて、

return Token::new(Token::get_keyword(&literal), literal);

これでいいのか

→共依存になるのでだめ。get_keywordはlexer.rs側で内部関数として定義すべき。

TokenがStirngであるのでそこのパフォーマンスはどうなのか?

Self::structfn(&self.field)みたいなのと、

self.structfn() どっちがいいんだろう。(後者は関数内でself.fieldにアクセスしている)

振り返り

アーキテクチャを先に大雑把に決めないと何も進まない

依存関係を考えてどこにfnを定義するか決めるべき。

概念理解 → 概念を具体的にしてモジュール化 → 設計図書く → (処理のフローをざっくり書いた方がよさげ?fnの具体性も上がるし) → 実際に書く → 適宜修正

-todo

  • test とエラー処理書いてない。
  • 何入れてもirregalになる…何がダメなのか全くわからん。→new でself.chに0をセットしてそれをinputの一文字目に変えることなくmatchしていた。new関数の中に一回read_step_charを入れることで解決。

リポジトリ
https://github.com/tai-calg/interpreter_in_Rust/tree/chapter1_lexer

Discussion

ログインするとコメントできます