Я очень новичок в Haskell, и мне нужно сделать рабочий калькулятор, что даст ответы на выражения типа: 2 + 3 * (5 + 12) У меня есть что-то, что позволяет вычислить больше или меньше, но у меня проблема с порядком операций. Я понятия не имею, как это сделать. Вот мой код:Калькулятор Haskell - порядок операций
import Text.Regex.Posix
import Data.Maybe
oblicz :: String -> Double
oblicz str = eval (Nothing, None) $ map convertToExpression $ (tokenize str)
eval :: (Maybe Double,Expression)->[Expression]->Double
eval (Nothing, _) ((Variable v):reszta) = eval (Just v, None) reszta
eval (Just aktualnyWynik, None) ((Operator o):reszta) = eval ((Just aktualnyWynik), (Operator o)) reszta
eval (Just aktualnyWynik, (Operator o)) ((Variable v):reszta) = eval (Just $ o aktualnyWynik v , None) reszta
eval (aktualnyWynik, operator) (LeftParenthesis:reszta)
= eval (aktualnyWynik, operator) ((Variable (eval (Nothing, None) reszta)):(getPartAfterParentheses reszta))
eval (Just aktualnyWynik, _) [] = aktualnyWynik
eval (Just aktualnyWynik, _) (RightParenthesis:_) = aktualnyWynik
data Expression = Operator (Double->Double->Double)
| Variable Double
| LeftParenthesis
| RightParenthesis
| None
tokenize :: String -> [String]
tokenize expression = getAllTextMatches(expression =~ "([0-9]+|\\(|\\)|\\+|-|%|/|\\*)" :: AllTextMatches [] String)
convertToExpression :: String -> Expression
convertToExpression "-" = Operator (-)
convertToExpression "+" = Operator (+)
convertToExpression "*" = Operator (*)
convertToExpression "/" = Operator (/)
convertToExpression "(" = LeftParenthesis
convertToExpression ")" = RightParenthesis
convertToExpression variable = Variable (read variable)
getPartAfterParentheses :: [Expression] -> [Expression]
getPartAfterParentheses [] = []
getPartAfterParentheses (RightParenthesis:expressionsList) = expressionsList
getPartAfterParentheses (LeftParenthesis:expressionsList) = getPartAfterParentheses (getPartAfterParentheses expressionsList)
getPartAfterParentheses (expression:expressionsList) = getPartAfterParentheses expressionsList
Я думал, может быть, я мог бы создать два стека - один с номерами и один с операторами. Читая выражение, я мог бы нажимать числа на один стек, а операторы - на другой. Когда это оператор, я бы проверил, есть ли что-то уже в стеке, и если есть проверка, следует ли мне поместить его из стека и выполнить математику или нет - точно так же, как в нотации onp.
К сожалению, как я уже сказал, я ОЧЕНЬ новичок в haskell и понятия не имею, как это писать.
Любые намеки или помощь будет приятно :)
«Этот вопрос не соответствует теме, потому что ** ему не хватает достаточной информации для диагностики проблемы **. Опишите вашу проблему более подробно или включите минимальный пример в самом вопросе». – gparyani
Можете ли вы привести пример ввода и выход? Как результат отличается от ожидаемого? –
'LeftParenthesis' не является' Expression', это только токен синтаксического анализа. Как только вы поймете это, вы увидите, что выражение нужно захватывать по-другому (например, Дерево, как в ответах ниже), где приоритет операций будет проявляться довольно прямолинейно. –