diff --git a/lib/ruby_algebra/command.rb b/lib/ruby_algebra/command.rb index c9f517e..3a7c643 100644 --- a/lib/ruby_algebra/command.rb +++ b/lib/ruby_algebra/command.rb @@ -21,6 +21,8 @@ module RubyAlgebra result += @lhs.is_a?(Array) ? @lhs.join(', ') : @lhs.to_s if @operation == :diff result += ' := Diff(' + @operand1.to_s + @operand2.map { |v| ", #{v}"}.join + ')' + elsif @operation == :subs + result += ' := Subs(' + @operand1.to_s + @operand2.map { |variable, value| ", #{variable}=#{value}"}.join + ')' else result += ' := ' + @operand1.to_s case @operation diff --git a/lib/ruby_algebra/parser.rb b/lib/ruby_algebra/parser.rb index 80ef029..5ff60d5 100644 --- a/lib/ruby_algebra/parser.rb +++ b/lib/ruby_algebra/parser.rb @@ -68,6 +68,14 @@ module RubyAlgebra end end + # Знак равенства = + class EqualsToken < Token + def initialize + super() + @type = :equals + end + end + # Запятая class CommaToken < Token def initialize @@ -141,7 +149,7 @@ module RubyAlgebra token = IdentifierToken.new(@expr[@i...j]) @i = j return token - elsif c.match(%r{[+\-*/^():,]}) + elsif c.match(%r{[+\-*/^():,=]}) puts 'operator' token = nil case c @@ -161,6 +169,8 @@ module RubyAlgebra token = ParenthesisToken.new(true) when ',' token = CommaToken.new + when '=' + token = EqualsToken.new end @i += 1 if c == ':' && @expr[@i] == '=' @@ -234,7 +244,43 @@ module RubyAlgebra end return AssignmentCommand.new(left_hand_side, :diff, target, diff_variables) elsif operand1.symbol == 'Subs' - raise NotImplementedError + tokenizer.next_token + n = tokenizer.next_token + unless n.type == :paren && n.closing == false + raise StandardError, "unexpected token #{n.type}, expected (" + end + n = tokenizer.lookahead + if n.type == :id && !n.variable? + tokenizer.next_token + target = n.symbol + else + target = parse_polynomial(tokenizer) + end + substitutions = {} + while tokenizer.lookahead.type == :comma + tokenizer.next_token + n = tokenizer.next_token + unless n.type == :id && n.variable? + raise StandardError, "unexpected token #{n.type}, expected variable" + end + variable = n.symbol + unless tokenizer.next_token.type == :equals + raise StandardError, "unexpected token #{n.type}, expected =" + end + n = tokenizer.next_token + unless n.type == :num + raise StandardError, "unexpected token #{n.type}, expected number" + end + substitutions[variable] = n.value + end + n = tokenizer.next_token + unless n.type == :paren && n.closing == true + raise StandardError, "unexpected token #{n.type}, expected )" + end + unless tokenizer.next_token.type == :end + raise StandardError, "unexpected token at the end" + end + return AssignmentCommand.new(left_hand_side, :subs, target, substitutions) else tokenizer.next_token operator = tokenizer.next_token