class BCDice::Command::Parser

よくある形式のコマンドのパースを補助するクラス

@example Literal by String

parser = Command::Parser.new("MC", round_type: BCDice::RoundType::FLOOR)
                        .enable_critical
parsed = parser.parse("MC+2*3@30<=10/2-3") #=> <Command::Parsed>

parsed.command #=> "MC"
parsed.modify_number #=> 6
parsed.critical #=> 30
parsed.cmp_op #=> #>=
parsed.target_number #=> 2

@example Literal by Regexp

parser = Command::Parser.new(/RE\d+/)
parsed = parser.parse("RE44+20") #=> <Command::Parsed>

parsed.command #=> "RE44"
parsed.modify_number #=> 20

Constants

Racc_arg
Racc_debug_parser
Racc_token_to_s_table

Public Class Methods

new(*notations, round_type:) click to toggle source

@param notations [Array<String, Regexp>] 反応するコマンドの表記 @param round_type [Symbol] 除算での端数の扱い

Calls superclass method
# File lib/bcdice/command/parser.rb, line 42
def initialize(*notations, round_type:)
  super()
  @notations = notations
  @round_type = round_type
  @prefix_number = false
  @suffix_number = false
  @need_prefix_number = false
  @need_suffix_number = false
  @modifier = true
  @critical = false
  @fumble = false
  @dollar = false
  @allowed_cmp_op = [nil, :>=, :>, :<=, :<, :==, :!=]
  @question_target = false
end

Public Instance Methods

disable_modifier() click to toggle source

修正値は受け付けないようにする @return [BCDice::Command::Parser]

# File lib/bcdice/command/parser.rb, line 60
def disable_modifier
  @modifier = false
  self
end
enable_critical() click to toggle source

+@+によるクリティカル値の指定を許可する @return [BCDice::Command::Parser]

# File lib/bcdice/command/parser.rb, line 97
def enable_critical
  @critical = true
  self
end
enable_dollar() click to toggle source

+$+による値の指定を許可する @return [BCDice::Command::Parser]

# File lib/bcdice/command/parser.rb, line 111
def enable_dollar
  @dollar = true
  self
end
enable_fumble() click to toggle source

+#+によるファンブル値の指定を許可する @return [BCDice::Command::Parser]

# File lib/bcdice/command/parser.rb, line 104
def enable_fumble
  @fumble = true
  self
end
enable_prefix_number() click to toggle source

リテラルの前に数値を許可する @return [BCDice::Command::Parser]

# File lib/bcdice/command/parser.rb, line 67
def enable_prefix_number
  @prefix_number = true
  self
end
enable_question_target() click to toggle source

目標値“?”の指定を許可する @return [BCDice::Command::Parser]

# File lib/bcdice/command/parser.rb, line 127
def enable_question_target
  @question_target = true
  self
end
enable_suffix_number() click to toggle source

リテラルの後ろに数値を許可する @return [BCDice::Command::Parser]

# File lib/bcdice/command/parser.rb, line 74
def enable_suffix_number
  @suffix_number = true
  self
end
has_prefix_number() click to toggle source

リテラルの前に数値が必要であると設定する @return [BCDice::Command::Parser]

# File lib/bcdice/command/parser.rb, line 81
def has_prefix_number
  @prefix_number = true
  @need_prefix_number = true
  self
end
has_suffix_number() click to toggle source

リテラルの後ろに数値が必要であると設定する @return [BCDice::Command::Parser]

# File lib/bcdice/command/parser.rb, line 89
def has_suffix_number
  @suffix_number = true
  @need_suffix_number = true
  self
end
parse(source) click to toggle source

@param source [String] @return [BCDice::Command::Parsed, nil]

# File lib/bcdice/command/parser.rb, line 134
def parse(source)
  @lexer = Lexer.new(source, @notations)
  do_parse()
rescue ParseError, ZeroDivisionError
  nil
end
restrict_cmp_op_to(*ops) click to toggle source

使用できる比較演算子を制限する。 目標値未入力を許可する場合にはnilを指定する。 @param ops [Array<nil, Symbol>] 許可する比較演算子の一覧 @return [BCDice::Command::Parser]

# File lib/bcdice/command/parser.rb, line 120
def restrict_cmp_op_to(*ops)
  @allowed_cmp_op = ops
  self
end

Private Instance Methods

_reduce_1(val, _values, result) click to toggle source

reduce 0 omitted

# File lib/bcdice/command/parser.rb, line 354
def _reduce_1(val, _values, result)
          raise ParseError unless @modifier
          notation, option, modifier, target = val
          result = parsed(notation, option, modifier, target)

    result
end
_reduce_10(val, _values, result) click to toggle source
# File lib/bcdice/command/parser.rb, line 423
def _reduce_10(val, _values, result)
            option, _, term = val
            raise ParseError unless @fumble && option[:fumble].nil?

            option[:fumble] = term
            result = option

    result
end
_reduce_11(val, _values, result) click to toggle source
# File lib/bcdice/command/parser.rb, line 433
def _reduce_11(val, _values, result)
            option, _, term = val
            raise ParseError unless @dollar && option[:dollar].nil?

            option[:dollar] = term
            result = option

    result
end
_reduce_12(val, _values, result) click to toggle source
# File lib/bcdice/command/parser.rb, line 443
def _reduce_12(val, _values, result)
 result = val[1]
    result
end
_reduce_13(val, _values, result) click to toggle source
# File lib/bcdice/command/parser.rb, line 448
def _reduce_13(val, _values, result)
 result = Arithmetic::Node::Negative.new(val[1])
    result
end
_reduce_14(val, _values, result) click to toggle source
# File lib/bcdice/command/parser.rb, line 453
def _reduce_14(val, _values, result)
 result = Arithmetic::Node::BinaryOp.new(val[0], :+, val[2])
    result
end
_reduce_15(val, _values, result) click to toggle source
# File lib/bcdice/command/parser.rb, line 458
def _reduce_15(val, _values, result)
 result = Arithmetic::Node::BinaryOp.new(val[0], :-, val[2])
    result
end
_reduce_16(val, _values, result) click to toggle source
# File lib/bcdice/command/parser.rb, line 463
def _reduce_16(val, _values, result)
            raise ParseError unless @allowed_cmp_op.include?(nil)
            result = {}

    result
end
_reduce_17(val, _values, result) click to toggle source
# File lib/bcdice/command/parser.rb, line 470
def _reduce_17(val, _values, result)
            cmp_op, target = val
            raise ParseError unless @allowed_cmp_op.include?(cmp_op)

            result = {cmp_op: cmp_op, target: target}

    result
end
_reduce_18(val, _values, result) click to toggle source
# File lib/bcdice/command/parser.rb, line 479
def _reduce_18(val, _values, result)
            cmp_op = val[0]
            raise ParseError unless @question_target
            raise ParseError unless @allowed_cmp_op.include?(cmp_op)

            result = {cmp_op: cmp_op, target: "?"}

    result
end
_reduce_19(val, _values, result) click to toggle source
# File lib/bcdice/command/parser.rb, line 489
def _reduce_19(val, _values, result)
 result = Arithmetic::Node::BinaryOp.new(val[0], :+, val[2])
    result
end
_reduce_2(val, _values, result) click to toggle source
# File lib/bcdice/command/parser.rb, line 362
def _reduce_2(val, _values, result)
          raise ParseError unless @modifier
          notation, modifier, option, target = val
          result = parsed(notation, option, modifier, target)

    result
end
_reduce_20(val, _values, result) click to toggle source
# File lib/bcdice/command/parser.rb, line 494
def _reduce_20(val, _values, result)
 result = Arithmetic::Node::BinaryOp.new(val[0], :-, val[2])
    result
end
_reduce_22(val, _values, result) click to toggle source

reduce 21 omitted

# File lib/bcdice/command/parser.rb, line 501
def _reduce_22(val, _values, result)
 result = Arithmetic::Node::BinaryOp.new(val[0], :*, val[2])
    result
end
_reduce_23(val, _values, result) click to toggle source
# File lib/bcdice/command/parser.rb, line 506
def _reduce_23(val, _values, result)
         divied_class = val[3]
         result = divied_class.new(val[0], val[2])

    result
end
_reduce_25(val, _values, result) click to toggle source

reduce 24 omitted

# File lib/bcdice/command/parser.rb, line 515
def _reduce_25(val, _values, result)
 result = Arithmetic::Node::DivideWithGameSystemDefault
    result
end
_reduce_26(val, _values, result) click to toggle source
# File lib/bcdice/command/parser.rb, line 520
def _reduce_26(val, _values, result)
 result = Arithmetic::Node::DivideWithCeil
    result
end
_reduce_27(val, _values, result) click to toggle source
# File lib/bcdice/command/parser.rb, line 525
def _reduce_27(val, _values, result)
 result = Arithmetic::Node::DivideWithCeil
    result
end
_reduce_28(val, _values, result) click to toggle source
# File lib/bcdice/command/parser.rb, line 530
def _reduce_28(val, _values, result)
 result = Arithmetic::Node::DivideWithRound
    result
end
_reduce_29(val, _values, result) click to toggle source
# File lib/bcdice/command/parser.rb, line 535
def _reduce_29(val, _values, result)
 result = Arithmetic::Node::DivideWithFloor
    result
end
_reduce_3(val, _values, result) click to toggle source
# File lib/bcdice/command/parser.rb, line 370
def _reduce_3(val, _values, result)
          notation, option, target = val
          result = parsed(notation, option,  Arithmetic::Node::Number.new(0), target)

    result
end
_reduce_30(val, _values, result) click to toggle source
# File lib/bcdice/command/parser.rb, line 540
def _reduce_30(val, _values, result)
 result = val[1]
    result
end
_reduce_31(val, _values, result) click to toggle source
# File lib/bcdice/command/parser.rb, line 545
def _reduce_31(val, _values, result)
 result = Arithmetic::Node::Negative.new(val[1])
    result
end
_reduce_33(val, _values, result) click to toggle source

reduce 32 omitted

# File lib/bcdice/command/parser.rb, line 552
def _reduce_33(val, _values, result)
 result = val[1]
    result
end
_reduce_34(val, _values, result) click to toggle source
# File lib/bcdice/command/parser.rb, line 557
def _reduce_34(val, _values, result)
 result = Arithmetic::Node::Number.new(val[0])
    result
end
_reduce_4(val, _values, result) click to toggle source
# File lib/bcdice/command/parser.rb, line 377
def _reduce_4(val, _values, result)
              raise ParseError unless @prefix_number && @suffix_number
              result = { command: val[1], prefix: val[0], suffix: val[2] }

    result
end
_reduce_5(val, _values, result) click to toggle source
# File lib/bcdice/command/parser.rb, line 384
def _reduce_5(val, _values, result)
              raise ParseError unless @prefix_number
              raise ParseError if @need_suffix_number
              result = { command: val[1], prefix: val[0] }

    result
end
_reduce_6(val, _values, result) click to toggle source
# File lib/bcdice/command/parser.rb, line 392
def _reduce_6(val, _values, result)
              raise ParseError unless @suffix_number
              raise ParseError if @need_prefix_number
              result = { command: val[0], suffix: val[1] }

    result
end
_reduce_7(val, _values, result) click to toggle source
# File lib/bcdice/command/parser.rb, line 400
def _reduce_7(val, _values, result)
              raise ParseError if @need_prefix_number || @need_suffix_number
              result = { command: val[0] }

    result
end
_reduce_8(val, _values, result) click to toggle source
# File lib/bcdice/command/parser.rb, line 407
def _reduce_8(val, _values, result)
            result = {}

    result
end
_reduce_9(val, _values, result) click to toggle source
# File lib/bcdice/command/parser.rb, line 413
def _reduce_9(val, _values, result)
            option, _, term = val
            raise ParseError unless @critical && option[:critical].nil?

            option[:critical] = term
            result = option

    result
end
_reduce_none(val, _values, result) click to toggle source
# File lib/bcdice/command/parser.rb, line 562
def _reduce_none(val, _values, result)
  val[0]
end
next_token() click to toggle source
# File lib/bcdice/command/parser.rb, line 163
def next_token
  @lexer.next_token
end
parsed(notation, option, modifier, target) click to toggle source
# File lib/bcdice/command/parser.rb, line 143
def parsed(notation, option, modifier, target)
  Parsed.new.tap do |p|
    p.command = notation[:command]
    p.prefix_number = notation[:prefix]&.eval(@round_type)
    p.suffix_number = notation[:suffix]&.eval(@round_type)
    p.critical = option[:critical]&.eval(@round_type)
    p.fumble = option[:fumble]&.eval(@round_type)
    p.dollar = option[:dollar]&.eval(@round_type)
    p.modify_number = modifier.eval(@round_type)
    p.cmp_op = target[:cmp_op]
    if target[:target] == "?"
      p.question_target = true
      p.target_number = 0
    else
      p.question_target = false
      p.target_number = target[:target]&.eval(@round_type)
    end
  end
end