привет, коммьюнити. сам я занимаюсь питоном, но, к сожалению, учусь в универе и там приходится выполнять лабы на других языках. Это код программы, которая преобразует привычную нам запись в польскую инверсную и считает результат (писал не сам, нашёл). и вроде бы все функции работают как надо, кроме string_to_expression. Она выдаёт ошибку:
?- calculate_string('1+2', R).
ERROR: >=/2: Arguments are not sufficiently instantiated
Exception: (8) string_to_expression(unary, '1+2', [], [], _G3195) ? creep
Как её исправить - понятия не имею. Может, есть тут те, кто шарят?
binary_operator(0'-, minus).
binary_operator(0'+, plus).
binary_operator(0'*, multiplication).
binary_operator(0'/, division).
unary_operator(0'-, unary_minus).
priority(open_bracket, -1).
priority(close_bracket, 0).
priority(plus, 1).
priority(minus, 1).
priority(multiplication, 2).
priority(division, 2).
priority(unary_minus, 3).
pop_stack_before_open_bracket([open_bracket|TailStack], PoppedBuffer, TailStack, PoppedBuffer):-!.
pop_stack_before_open_bracket([Head|TailStack], ExpressionBuffer, PoppedStack, PoppedBuffer):-
pop_stack_before_open_bracket(TailStack, [Head|ExpressionBuffer], PoppedStack, PoppedBuffer).
pop_stack_before_less_priority(_Priority, [], PoppedBuffer, [], PoppedBuffer):-!.
pop_stack_before_less_priority(Priority, [HeadStack|TailStack], PoppedBuffer, [HeadStack|TailStack], PoppedBuffer):-
priority(HeadStack, HeadStackPriority), HeadStackPriority < Priority, !. % stop popping
pop_stack_before_less_priority(Priority, [HeadStack|TailStack], ExpressionBuffer, PoppedStack, PoppedBuffer):-
pop_stack_before_less_priority(Priority, TailStack, [HeadStack|ExpressionBuffer], PoppedStack, PoppedBuffer).
symbol_to_digit(DigitSymbol, Digit):-
DigitSymbol >= 0'0, DigitSymbol =< 0'9,
Digit is DigitSymbol - 0'0.
get_positive(String, Number, TailString):-
symbol_to_digit(_, _Digit), !,
get_positive(integral, 0, String, Number, TailString).
get_positive(integral, IntegralPart, [0'.|Tail], Number, TailString):-
!, get_positive(fraction, 0, 10, Tail, FractionPart, TailString),
Number is IntegralPart + FractionPart.
get_positive(integral, IntegralPart, [HeadDigit|Tail], Number, TailString):-
symbol_to_digit(HeadDigit, Digit), !,
TailIntegralPart is IntegralPart*10 + Digit,
get_positive(integral, TailIntegralPart, Tail, Number, TailString).
get_positive(integral, Number, String, Number, String):-!.
get_positive(fraction, FractionPart, Factor, [HeadDigit|Tail], Number, TailString):-
symbol_to_digit(HeadDigit, Digit), !,
TailFractionPart is FractionPart + Digit/Factor,
TailFactor is Factor*10,
get_positive(fraction, TailFractionPart, TailFactor, Tail, Number, TailString).
get_positive(fraction, Number, _TailFactor, String, Number, String).
string_to_expression(_BinaryOrUnary, "", Stack, Buffer, Expression):-
/* if string is empty - pop the stack */
!, reverse(Stack, ReversedStack),
append(ReversedStack, Buffer, ReversedExpression),
reverse(ReversedExpression, Expression).
string_to_expression(_BinaryOrUnary, String, Stack, Buffer, Expression):-
/* if read the number - push it into buffer */
get_positive(String, Number, TailString), !,
string_to_expression(binary, TailString, Stack, [(number, Number)|Buffer], Expression).
string_to_expression(_BinaryOrUnary, [0'(|TailString], Stack, Buffer, Expression):-
/* if read the open bracket - push it into stack */
!, string_to_expression(unary, TailString, [open_bracket|Stack], Buffer, Expression).
string_to_expression(_BinaryOrUnary, [0')|TailString], Stack, Buffer, Expression):-
/* if read the close bracket - pop stack before open bracket */
!, pop_stack_before_open_bracket(Stack, Buffer, PoppedStack, PoppedBuffer),
string_to_expression(binary, TailString, PoppedStack, PoppedBuffer, Expression).
string_to_expression(binary, [OperatorSymbol|TailString], Stack, Buffer, Expression):-
/* if read binary_operator - pop stack before head stack has bigger or equal priority than that binary_operator */
binary_operator(OperatorSymbol, Operator), !,
priority(Operator, OperatorPriority),
pop_stack_before_less_priority(OperatorPriority, Stack, Buffer, PoppedStack, PoppedBuffer),
string_to_expression(unary, TailString, [Operator|PoppedStack], PoppedBuffer, Expression).
string_to_expression(unary, [OperatorSymbol|TailString], Stack, Buffer, Expression):-
unary_operator(OperatorSymbol, UnaryOperator),
priority(UnaryOperator, OperatorPriority),
pop_stack_before_less_priority(OperatorPriority, Stack, Buffer, PoppedStack, PoppedBuffer),
string_to_expression(unary, TailString, [UnaryOperator|PoppedStack], PoppedBuffer, Expression).
calculate_binary_operator(plus, LeftOperand, RightOperand, Result):-
!, Result is LeftOperand + RightOperand.
calculate_binary_operator(minus, LeftOperand, RightOperand, Result):-
!, Result is LeftOperand - RightOperand.
calculate_binary_operator(multiplication, LeftOperand, RightOperand, Result):-
!, Result is LeftOperand * RightOperand.
calculate_binary_operator(division, LeftOperand, RightOperand, Result):-
!, Result is LeftOperand / RightOperand.
calculate_unary_operator(unary_minus, Operand, OperatorResult):-
OperatorResult is -Operand.
calculate_reverse_polish_notation([], [Result], Result):-!.
calculate_reverse_polish_notation([(number, Value)|Tail], Operands, Result):-
calculate_reverse_polish_notation(Tail, [Value|Operands], Result), !.
calculate_reverse_polish_notation([UnaryOperator|Tail], [Operand|TailOperands], Result):-
calculate_unary_operator(UnaryOperator, Operand, OperatorResult),
calculate_reverse_polish_notation(Tail, [OperatorResult|TailOperands], Result).
calculate_reverse_polish_notation([Operator|Tail], [RightOperand, LeftOperand|TailOperands], Result):-
calculate_binary_operator(Operator, LeftOperand, RightOperand, OperatorResult),
calculate_reverse_polish_notation(Tail, [OperatorResult|TailOperands], Result).
calculate_string(String, Result):-
string_to_expression(unary, String, [], [], E),
calculate_reverse_polish_notation(E, [], Result).