😺

PEGパーサーのParsletで、0から999までの数字と0埋め3桁の数字を解析した

2023/04/16に公開
1

PEGパーサーのParsletで、0から999までの数字と0埋め3桁の数字を解析してみました。

書いてみた

# frozen_string_literal: true

require 'rspec'
require 'parslet'

# 10進数の0から999までの数字
class NumberParser1 < Parslet::Parser
  root :integer

  rule(:integer) do
    match('\d') | match('[1-9]') >> match('\d').repeat(1, 2)
  end
end

RSpec.describe NumberParser1 do
  describe '.parser' do
    subject { described_class.new.parse(raw_string) }

    context '0を解析する場合' do
      let(:raw_string) { '0' }

      it { is_expected.to eq '0' }
    end

    context '000を解析する場合' do
      let(:raw_string) { '000' }

      it { expect { subject }.to raise_error(Parslet::ParseFailed) }
    end

    context '10を解析する場合' do
      let(:raw_string) { '10' }

      it { is_expected.to eq '10' }
    end

    context '010を解析する場合' do
      let(:raw_string) { '000' }

      it { expect { subject }.to raise_error(Parslet::ParseFailed) }
    end

    context '100を解析する場合' do
      let(:raw_string) { '100' }

      it { is_expected.to eq '100' }
    end

    context '999を解析する場合' do
      let(:raw_string) { '999' }

      it { is_expected.to eq '999' }
    end
  end
end

# 10進数の0埋め3桁の数字
class NumberParser2 < Parslet::Parser
  root :integer

  rule(:integer) { digit.repeat(3) }
  rule(:digit) { match['0-9'] }
end

RSpec.describe NumberParser2 do
  describe '.parser' do
    subject { described_class.new.parse(raw_string) }

    context '0を解析する場合' do
      let(:raw_string) { '0' }

      it { expect { subject }.to raise_error(Parslet::ParseFailed) }
    end

    context '000を解析する場合' do
      let(:raw_string) { '000' }

      it { is_expected.to eq '000' }
    end

    context '10を解析する場合' do
      let(:raw_string) { '10' }

      it { expect { subject }.to raise_error(Parslet::ParseFailed) }
    end

    context '010を解析する場合' do
      let(:raw_string) { '010' }

      it { is_expected.to eq '010' }
    end

    context '100を解析する場合' do
      let(:raw_string) { '100' }

      it { is_expected.to eq '100' }
    end

    context '999を解析する場合' do
      let(:raw_string) { '999' }

      it { is_expected.to eq '999' }
    end
  end
end

感想

久方ぶりにPEGパーサーのParsletを使いました。なつかしいですね〜。https://bford.info/pub/lang/peg/ に論文が落ちているのもみつけたので、良い機会に読んでみたいです。

Discussion