add diff command variant

This commit is contained in:
2026-04-13 14:57:03 +03:00
parent d8a24a1349
commit 286e79f21a
2 changed files with 78 additions and 38 deletions

View File

@@ -19,19 +19,22 @@ module RubyAlgebra
def to_s
result = "Assignment command: "
result += @lhs.is_a?(Array) ? @lhs.join(', ') : @lhs.to_s
result += ' := '
result += @operand1.to_s
case @operation
when :add
result += ' + '
when :sub
result += ' - '
when :mult, :scale
result += ' * '
when :div
result += ' / '
if @operation == :diff
result += ' := Diff(' + @operand1.to_s + @operand2.map { |v| ", #{v}"}.join + ')'
else
result += ' := ' + @operand1.to_s
case @operation
when :add
result += ' + '
when :sub
result += ' - '
when :mult, :scale
result += ' * '
when :div
result += ' / '
end
result += @operand2.to_s if @operation != :assign
end
result += @operand2.to_s if @operation != :assign
result
end
end

View File

@@ -141,7 +141,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
@@ -159,6 +159,8 @@ module RubyAlgebra
token = ParenthesisToken.new(false)
when ')'
token = ParenthesisToken.new(true)
when ','
token = CommaToken.new
end
@i += 1
if c == ':' && @expr[@i] == '='
@@ -200,33 +202,68 @@ module RubyAlgebra
if tokenizer.lookahead.type == :assign
n = tokenizer.next_token
operand1 = tokenizer.lookahead
unless operand1.type == :id && !operand1.variable?
return AssignmentCommand.new(left_hand_side, :assign, parse_polynomial(tokenizer), nil)
end
tokenizer.next_token
operator = tokenizer.next_token
raise StandardError, "unexpected token #{operator.type}, expected +, -, * or /" unless [:plus, :minus, :mult, :div].include?(operator.type)
operand2 = tokenizer.next_token
unless ([:plus, :minus, :mult].include?(operator.type) && operand2.type == :id && !operand2.variable?) ||
([:mult, :div].include?(operator.type) && operand2.type == :num)
raise StandardError, 'unsupported operation or invalid syntax'
end
if operand2.type == :num
if operator.type == :mult
return AssignmentCommand.new(left_hand_side, :scale, operand1.symbol, operand2.value)
if operand1.type == :id && !operand1.variable?
if operand1.symbol == 'Diff'
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
diff_variables = []
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
diff_variables << n.symbol
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, :diff, target, diff_variables)
elsif operand1.symbol == 'Subs'
raise NotImplementedError
else
return AssignmentCommand.new(left_hand_side, :scale, operand1.symbol, 1.0 / operand2.value)
end
elsif operand2.type == :id
case operator.type
when :plus
return AssignmentCommand.new(left_hand_side, :add, operand1.symbol, operand2.symbol)
when :minus
return AssignmentCommand.new(left_hand_side, :sub, operand1.symbol, operand2.symbol)
when :mult
return AssignmentCommand.new(left_hand_side, :mult, operand1.symbol, operand2.symbol)
tokenizer.next_token
operator = tokenizer.next_token
raise StandardError, "unexpected token #{operator.type}, expected +, -, * or /" unless [:plus, :minus, :mult, :div].include?(operator.type)
operand2 = tokenizer.next_token
unless ([:plus, :minus, :mult].include?(operator.type) && operand2.type == :id && !operand2.variable?) ||
([:mult, :div].include?(operator.type) && operand2.type == :num)
raise StandardError, 'unsupported operation or invalid syntax'
end
if operand2.type == :num
if operator.type == :mult
return AssignmentCommand.new(left_hand_side, :scale, operand1.symbol, operand2.value)
else
return AssignmentCommand.new(left_hand_side, :scale, operand1.symbol, 1.0 / operand2.value)
end
elsif operand2.type == :id
case operator.type
when :plus
return AssignmentCommand.new(left_hand_side, :add, operand1.symbol, operand2.symbol)
when :minus
return AssignmentCommand.new(left_hand_side, :sub, operand1.symbol, operand2.symbol)
when :mult
return AssignmentCommand.new(left_hand_side, :mult, operand1.symbol, operand2.symbol)
end
end
end
else
return AssignmentCommand.new(left_hand_side, :assign, parse_polynomial(tokenizer), nil)
end
elsif tokenizer.lookahead.type == :comma
n = tokenizer.next_token