Parsing/RPN to infix conversion: Difference between revisions

Content added Content deleted
(→‎{{header|Haskell}}: Added trace of stack, updated output.)
Line 1,915: Line 1,915:
data Expression = Const String | Exp Expression String Expression
data Expression = Const String | Exp Expression String Expression


------------- INFIX EXPRESSION FROM RPN STRING -----------
precedence :: Expression -> Int
precedence (Const _) = 5
precedence (Exp _ op _)
| op == "^" = 4
| op `elem` ["*", "/"] = 3
| op `elem` ["+", "-"] = 2
| otherwise = 0


infixFromRPN :: String -> Expression
leftAssoc :: Expression -> Bool
infixFromRPN = head . foldl buildExp [] . words
leftAssoc (Const _) = False
leftAssoc (Exp _ op _) = op `notElem` ["^", "*", "+"]

rightAssoc :: Expression -> Bool
rightAssoc (Const _) = False
rightAssoc (Exp _ op _) = op == "^"

instance Show Expression where
show (Const x) = x
show exp@(Exp l op r) = left <> " " <> op <> " " <> right
where
left
| leftNeedParen = "( " <> show l <> " )"
| otherwise = show l
right
| rightNeedParen = "( " <> show r <> " )"
| otherwise = show r
leftNeedParen =
(leftPrec < opPrec)
|| ((leftPrec == opPrec) && rightAssoc exp)
rightNeedParen =
(rightPrec < opPrec)
|| ((rightPrec == opPrec) && leftAssoc exp)
leftPrec = precedence l
rightPrec = precedence r
opPrec = precedence exp


buildExp :: [Expression] -> String -> [Expression]
buildExp :: [Expression] -> String -> [Expression]
Line 1,963: Line 1,932:
isOp = (`elem` ["^", "*", "/", "+", "-"])
isOp = (`elem` ["^", "*", "/", "+", "-"])



--------------------------- TEST -------------------------
main :: IO ()
main :: IO ()
main =
main =
Line 1,968: Line 1,939:
( \s ->
( \s ->
putStr (s <> "\n-->\n")
putStr (s <> "\n-->\n")
>> (print . head . foldl buildExp [] . words)
>> (print . infixFromRPN)
s
s
>> putStrLn []
>> putStrLn []
Line 1,977: Line 1,948:
"1 2 * 3 4 * *",
"1 2 * 3 4 * *",
"1 2 + 3 4 + +"
"1 2 + 3 4 + +"
]</lang>
]

---------------------- SHOW INSTANCE ---------------------
instance Show Expression where
show (Const x) = x
show exp@(Exp l op r) = left <> " " <> op <> " " <> right
where
left
| leftNeedParen = "( " <> show l <> " )"
| otherwise = show l
right
| rightNeedParen = "( " <> show r <> " )"
| otherwise = show r
leftNeedParen =
(leftPrec < opPrec)
|| ((leftPrec == opPrec) && rightAssoc exp)
rightNeedParen =
(rightPrec < opPrec)
|| ((rightPrec == opPrec) && leftAssoc exp)
leftPrec = precedence l
rightPrec = precedence r
opPrec = precedence exp

leftAssoc :: Expression -> Bool
leftAssoc (Const _) = False
leftAssoc (Exp _ op _) = op `notElem` ["^", "*", "+"]

rightAssoc :: Expression -> Bool
rightAssoc (Const _) = False
rightAssoc (Exp _ op _) = op == "^"

precedence :: Expression -> Int
precedence (Const _) = 5
precedence (Exp _ op _)
| op == "^" = 4
| op `elem` ["*", "/"] = 3
| op `elem` ["+", "-"] = 2
| otherwise = 0</lang>
{{Out}}
{{Out}}
<pre>3 4 2 * 1 5 - 2 3 ^ ^ / +
<pre>3 4 2 * 1 5 - 2 3 ^ ^ / +