require "ruby_algebra" RSpec.describe RubyAlgebra::Parser do # Хелпер для быстрой сборки ожидаемых многочленов в тестах def build_poly(terms_array) terms = terms_array.map do |t| RubyAlgebra::Term.new(t[:coeff], t[:vars] || {}) end RubyAlgebra::Polynomial.new(terms) end describe '.parse_polynomial' do let(:tokenizer) { ->(str) { RubyAlgebra::Parser::Tokenizer.new(str) } } it 'парсит простое число как константный многочлен' do result = RubyAlgebra::Parser.parse_polynomial(tokenizer.call("42")) expect(result).to eq(build_poly([{ coeff: 42 }])) end it 'парсит одиночную переменную' do result = RubyAlgebra::Parser.parse_polynomial(tokenizer.call("x")) expect(result).to eq(build_poly([{ coeff: 1, vars: { "x" => 1 } }])) end it 'парсит многочлен с несколькими термами и степенями' do # 2x^2 + 3x - 5 result = RubyAlgebra::Parser.parse_polynomial(tokenizer.call("2x^2 + 3x - 5")) expected = build_poly([ { coeff: 2, vars: { "x" => 2 } }, { coeff: 3, vars: { "x" => 1 } }, { coeff: -5, vars: {} } ]) expect(result).to eq(expected) end it 'обрабатывает отрицательный первый терм' do result = RubyAlgebra::Parser.parse_polynomial(tokenizer.call("-x + 1")) expect(result).to eq(build_poly([ { coeff: -1, vars: { "x" => 1 } }, { coeff: 1 } ])) end end describe '.parse_command' do context 'Арифметические операции (взаимодействие многочленов)' do it 'парсит команду сложения: C := A + B' do cmd = RubyAlgebra::Parser.parse_command("C := A + B") expect(cmd).to be_a(RubyAlgebra::AssignmentCommand) expect(cmd.operation).to eq(:add) expect(cmd.lhs).to eq("C") expect(cmd.operand1).to eq("A") expect(cmd.operand2).to eq("B") end it 'парсит команду вычитания: Result := P1 - P2' do cmd = RubyAlgebra::Parser.parse_command("Result := P1 - P2") expect(cmd.operation).to eq(:sub) expect(cmd.operand1).to eq("P1") expect(cmd.operand2).to eq("P2") end it 'парсит команду умножения: M := Poly1 * Poly2' do cmd = RubyAlgebra::Parser.parse_command("M := Poly1 * Poly2") expect(cmd.operation).to eq(:mult) expect(cmd.operand1).to eq("Poly1") expect(cmd.operand2).to eq("Poly2") end it 'парсит деление с остатком: Q, R := A / B' do cmd = RubyAlgebra::Parser.parse_command("Q, R := A / B") expect(cmd.operation).to eq(:div) expect(cmd.lhs).to eq(["Q", "R"]) expect(cmd.operand1).to eq("A") expect(cmd.operand2).to eq("B") end end context 'Операции с числами (Scales)' do it 'парсит умножение на число как :scale' do cmd = RubyAlgebra::Parser.parse_command("A := B * 10") expect(cmd.operation).to eq(:scale) expect(cmd.operand2).to eq(10) end it 'парсит деление на число как :scale с инверсией' do cmd = RubyAlgebra::Parser.parse_command("A := B / 2") expect(cmd.operation).to eq(:scale) expect(cmd.operand2).to eq(0.5) end end context 'Специальные методы' do it 'парсит дифференцирование: D := Diff(P, x)' do cmd = RubyAlgebra::Parser.parse_command("D := Diff(P, x)") expect(cmd.operation).to eq(:diff) expect(cmd.operand1).to eq("P") expect(cmd.operand2).to eq(["x"]) end it 'парсит подстановку: S := Subs(P, x=2, y=3)' do cmd = RubyAlgebra::Parser.parse_command("S := Subs(P, x=2, y=3)") expect(cmd.operation).to eq(:subs) expect(cmd.operand1).to eq("P") expect(cmd.operand2).to eq({ "x" => 2, "y" => 3 }) end end it 'парсит команду вывода (Display)' do cmd = RubyAlgebra::Parser.parse_command("A") expect(cmd).to be_a(RubyAlgebra::DisplayCommand) expect(cmd.item).to eq("A") end end end RSpec.describe RubyAlgebra::Interpreter do let(:interpreter) { RubyAlgebra::Interpreter.new } it 'выполняет цепочку: присваивание и сложение' do # Создаем полиномы через парсер и выполняем команды через интерпретатор p1_cmd = RubyAlgebra::Parser.parse_command("A := 2x") p2_cmd = RubyAlgebra::Parser.parse_command("B := 3x + 1") add_cmd = RubyAlgebra::Parser.parse_command("C := A + B") interpreter.execute(p1_cmd) interpreter.execute(p2_cmd) result_str = interpreter.execute(add_cmd) expect(result_str).to include("5x + 1") end it 'выполняет деление с остатком' do # (x^2 - 1) / (x - 1) = x + 1, остаток 0 interpreter.execute(RubyAlgebra::Parser.parse_command("A := 1x^2 - 1")) interpreter.execute(RubyAlgebra::Parser.parse_command("B := 1x - 1")) # В вашей грамматике деление: Q, R := A / B cmd = RubyAlgebra::Parser.parse_command("Q, R := A / B") interpreter.execute(cmd) expect(interpreter.execute(RubyAlgebra::Parser.parse_command("Q"))).to eq("1.0x + 1.0") expect(interpreter.execute(RubyAlgebra::Parser.parse_command("R"))).to eq("0") end end