Haskell, 211 197 197186 bytes
(Saved 10 bytes by using interact
as suggested by @Challenger5, and one more by not having a final newline.)
m(')':r)=([],r)
m s|(a,u)<-e s,(b,v)<-m u=(a:b,v)
f s|(a,r)<-m s=(tail(a>>"`"):a>>=id,r)
e('\\':v:_:s)|(a,r)<-f s=('\\':v:a,')':r)
e('(':s)=f s
e(v:s)=([v],s)
main=getLine>>=putStrLn.fstmain=interact$fst.f.(++")")
Initially I had a function to perform the whole transformation, but now that is inlined into the main
function which makes it a complete program. Using getLine
andDealing with a complete program instead of using a function putStrLnString -> String
at the interpreter also avoids the need to type and read double backslashes. The other functions follow the (simplified) pure functional parsing pattern of returning a parsing result and the unparsed rest of the string. f
parses a list of expressions (possibly a multiple application) . It uses a helper function m
that also parses a list of expressions and has a list of parses as result. e
handles the remaining cases: lambdas, parenthesized expressions, and variables. Instead of generating a parsing tree, we directly generate the desired output.
Compile withTry it online!
Using ghcinteract
ruined clean I/O behaviour. If you don't use the TIO link but run it at the command line of your computer, you have to make sure that there is no trailing whitespace, it would be treated like a variable. You can do something like echo -on lam'\f.(\x.xx)\x.f(xx)' lam| .hs/prog
and give input to stdin:. Alternatively, you could replace the last line by the previous version main=getLine>>=putStrLn.fst.f.(++")")
.
$ ./lam
\f.(\x.xx)\x.f(xx)
\f`\x`xx\x`f`xx