@KartoshkaD

Где закралась ошибка?

привет, коммьюнити. сам я занимаюсь питоном, но, к сожалению, учусь в универе и там приходится выполнять лабы на других языках. Это код программы, которая преобразует привычную нам запись в польскую инверсную и считает результат (писал не сам, нашёл). и вроде бы все функции работают как надо, кроме 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).
  • Вопрос задан
  • 231 просмотр
Решения вопроса 1
alsopub
@alsopub
Подправил программу, теперь она работает в swish.swi-prolog.org

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([S|T], Number, TailString):-
    symbol_to_digit(S, _Digit), !,
    get_positive(integral, 0, [S|T], 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_list(String, L),
    string_to_expression(unary, L, [], [], E),
    calculate_reverse_polish_notation(E, [], Result).
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы