Ответы пользователя по тегу Prolog
  • Где закралась ошибка?

    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).
    Ответ написан