Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Yuhi-Sato/jp-ruby

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

jp-ruby

日本語でRubyを書こう。

jp-rubyは、Rubyの文法を日本語キーワードで記述できるプリプロセッサです。.jrbファイルに日本語でコードを書き、jp-rubyコマンドで実行できます。

インストール

git clone https://github.com/jp-ruby/jp-ruby.git
cd jp-ruby
bundle install

使い方

ファイルを実行する

bundle exec ruby exe/jp-ruby examples/hello_world.jrb

インラインで実行する

bundle exec ruby exe/jp-ruby -e '表示 "こんにちは、世界!"'

変換後のRubyコードを確認する

bundle exec ruby exe/jp-ruby --dump examples/animal_classes.jrb

Hello World

# hello_world.jrb
表示 "こんにちは、世界!"

クラスと継承

# animal_classes.jrb
クラス 動物
  定義 初期化(名前)
    @名前 = 名前
  終わり

  定義 自己紹介
    表示 "私は#{@名前}です。"
  終わり
終わり

クラス  < 動物
  定義 吠える
    表示 "#{@名前}: ワンワン!"
  終わり
終わり

ポチ = .新規("ポチ")
ポチ.自己紹介
ポチ.吠える

出力:

私はポチです。
ポチ: ワンワン!

FizzBuzz

# fizzbuzz.jrb
定義 フィズバズ()
  もし  % 15 == 0
    "フィズバズ"
  そうでなければ  % 3 == 0
    "フィズ"
  そうでなければ  % 5 == 0
    "バズ"
  でなければ
    .文字列変換
  終わり
終わり

1.まで上(100) する |i|
  表示 フィズバズ(i)
終わり

パターンマッチング

# pattern_match.jrb
定義 ステータス確認(応答)
  場合 応答
  中の { ステータス: 200, 本文: }
    表示 "成功: #{本文}"
  中の { ステータス: 404 }
    表示 "見つかりません"
  終わり
終わり

itブロックパラメータ

# block_it.jrb
数列 = [1, 2, 3, 4, 5]
二倍 = 数列.変換 { それ * 2 }
表示 二倍.検査

キーワード対応表

定義・構造

日本語 Ruby
クラス class
モジュール module
定義 def
終わり end
初期化 initialize
新規 new

制御構文

日本語 Ruby
もし if
そうでなければ elsif
でなければ else
でない限り unless
場合 case
条件 when
そして then

ループ・ブロック

日本語 Ruby
繰り返す while
まで until
繰り返し for
中の in
する do

リテラル

日本語 Ruby
true
false
nil

フロー制御

日本語 Ruby
戻す return
次へ next
中断 break
譲る yield
自分 self
super

例外処理

日本語 Ruby
始まり begin
救済 rescue
確保 ensure
発生 raise

モジュール・アクセス

日本語 Ruby
取り込む include
拡張 extend
公開 public
非公開 private
保護 protected
必要 require

論理演算子

日本語 Ruby
かつ and
または or
ではない not

入出力

日本語 Ruby
表示 puts
出力 print
検査 p

属性

日本語 Ruby
属性 attr_accessor
読み属性 attr_reader
書き属性 attr_writer

itやRactor、Dataなどの新しい構文

日本語 Ruby
それ it
ラクター Ractor
データ Data

メソッドエイリアス

キーワード変換に加えて、組み込みクラスのメソッドにも日本語エイリアスが利用できます。

Array

日本語 Ruby
それぞれ each
変換 map
選択 select
除外 reject
畳み込み reduce
並べ替え sort
逆順 reverse
一意 uniq
含む? include?
追加 push
長さ length
空? empty?
結合 join
最初 first
最後 last

Hash

日本語 Ruby
それぞれ each
鍵一覧 keys
値一覧 values
含む? include?
結合 merge
削除 delete

String

日本語 Ruby
長さ length
分割 split
含む? include?
置換 gsub
大文字 upcase
小文字 downcase
除去 strip
空? empty?
整数変換 to_i
小数変換 to_f

Integer

日本語 Ruby
times
偶数? even?
奇数? odd?
文字列変換 to_s
絶対値 abs

Object

日本語 Ruby
凍結 freeze
凍結済み? frozen?
複製 dup
は? is_a?

アーキテクチャ

全体の処理フロー

                         jp-ruby 実行パイプライン
┌─────────┐    ┌──────────────┐    ┌──────────────┐    ┌──────────┐
│  .jrb   │───>│  Tokenizer   │───>│  Transpiler  │───>│  Runner  │
│ ファイル │    │トークナイザー │    │トランスパイラー│    │  実行    │
└─────────┘    └──────────────┘    └──────────────┘    └──────────┘
                     │                    │                   │
                     ▼                    ▼                   ▼
               トークン列に分解      日本語→Ruby変換     Runtime読み込み
               (コード/文字列/       + クラス名に        + eval実行
                コメントを区別)       Cプレフィックス付与

ディレクトリ構造

jp-ruby/
├── exe/
│   └── jp-ruby                 # CLI エントリーポイント(OptionParser)
├── lib/
│   ├── jp_ruby.rb              # メインモジュール(全コンポーネントの読み込み)
│   └── jp_ruby/
│       ├── version.rb          # バージョン定数
│       ├── errors.rb           # TranspileError, TokenizeError
│       ├── keywords.rb         # 日本語→Ruby キーワードマッピング(50+語)
│       ├── tokenizer.rb        # StringScannerベースのステートマシン
│       ├── transpiler.rb       # 2パストランスパイラー
│       ├── runtime.rb          # 組み込みクラスへのメソッドエイリアス定義
│       └── runner.rb           # ファイル読み込み→変換→実行の統括
├── spec/                       # RSpec テスト(84テスト)
└── examples/                   # サンプル .jrb ファイル

コンポーネント詳細

1. Tokenizer(トークナイザー)

StringScannerベースのステートマシンで、ソースコードをトークン列に分解します。各トークンにはコンテキスト(コード / 文字列 / コメント等)が付与され、トランスパイラーが「どこを置換すべきか」を正確に判断できます。

             ステートマシン状態遷移

    ┌──────┐  "   ┌───────────────┐
    │ CODE │─────>│ DOUBLE_STRING │
    │      │<─────│               │
    │      │  "   └───────┬───────┘
    │      │              │ #{
    │      │              ▼
    │      │      ┌───────────────┐
    │      │      │ INTERPOLATION │ ← コードとして処理
    │      │      │ (ブレース深度  │   }で元の状態に復帰
    │      │      │  を追跡)      │
    │      │      └───────────────┘
    │      │
    │      │  '   ┌───────────────┐
    │      │─────>│ SINGLE_STRING │
    │      │<─────│               │
    │      │  '   └───────────────┘
    │      │
    │      │  #   ┌─────────┐
    │      │─────>│ COMMENT │──> 行末で復帰
    │      │      └─────────┘
    │      │
    │      │=begin┌───────────────┐
    │      │─────>│ MULTI_COMMENT │
    │      │<─────│               │
    │      │=end  └───────────────┘
    │      │
    │      │  /   ┌───────┐
    │      │─────>│ REGEX │
    │      │<─────│       │
    │      │  /   └───────┘
    │      │
    │      │ <<~  ┌────────┐
    │      │─────>│HEREDOC │
    │      │<─────│        │
    └──────┘      └────────┘

トークン種別:

種別 説明 キーワード置換
:word 識別子・キーワード 対象
:string_part 文字列リテラルの中身 対象外
:comment コメント 対象外
:interp_begin / :interp_end #{} -
:space 空白・改行 -
:other 演算子・記号・数値 -

ワードパターン: /[\p{L}_][\p{L}\p{N}_]*[?!]?/ で日本語文字(漢字・ひらがな・カタカナ)を含む識別子にマッチします。

2. Transpiler(トランスパイラー)

2パスでトークン列を変換します。

Pass 1: クラス名収集                  Pass 2: 置換

 トークン列を走査                      各 :word トークンに対して

 "クラス" の次の :word を収集           1. クラス名?  → Cプレフィックス付与
                                      2. キーワード? → Ruby変換
 例: クラス 犬                         3. それ以外   → そのまま
   → ["犬"] を記録
                                      例: 犬     → C犬
 ※日本語名のみ対象                         クラス → class
                                          吠える → 吠える (変換なし)

クラス名のCプレフィックス: Rubyでは定数(クラス名・モジュール名)は大文字ASCII [A-Z] で始まる必要があります。日本語クラス名は C プレフィックスを自動付与することで、ユーザーが意識せずに日本語クラス名を使えるようにしています。

入力:  クラス 犬 < 動物        出力:  class C犬 < C動物
         犬.新規("ポチ")              C犬.new("ポチ")

行構造の保持: キーワード置換は行の追加・削除を行わないため、変換後のRubyコードの行番号は元の .jrb ファイルと完全に一致します。エラー発生時のスタックトレースがそのまま .jrb ファイルの行番号を指します。

3. Runtime(ランタイム)

実行前に alias_method で組み込みクラスにメソッドエイリアスを追加します。キーワード変換では対応できないメソッド呼び出し(.each, .map 等)を日本語化するための仕組みです。

# 内部的に行われること
Array.class_eval do
  alias_method :それぞれ, :each
  alias_method :変換, :map
  alias_method :選択, :select
  # ...
end

4. Runner(ランナー)

全コンポーネントを統括する実行エンジンです。

Runner#run の処理フロー:

  1. File.read(filename, encoding: "UTF-8")
  2. Transpiler.new(source).transpile
  3. Runtime.load!  (メソッドエイリアス登録)
  4. eval(ruby_code, TOPLEVEL_BINDING, filename, 1)
                                        ~~~~~~~~  ~
                                        元ファイル名と行番号を渡すことで
                                        エラー時の表示が正確になる

設計上のポイント

課題 解決策
文字列内のキーワード誤置換 ステートマシンで文字列/コメント内を区別
#{}内は置換が必要 INTERPOLATION状態でコードモードに復帰
日本語クラス名がRubyの定数規則に反する 自動でCプレフィックスを付与
部分一致による誤変換(例: 終わりました終わり がマッチ) トークナイザーが単語単位でスキャンするため発生しない
エラー時の行番号ずれ 行構造を変えない置換 + evalに元ファイル名を渡す
キーワードの長さによる誤マッチ マッピングを文字列長の降順でソート

動作環境

  • Ruby >= 3.2.0

テスト

bundle exec rspec

ライセンス

MIT License

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages