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

View File

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