Scala isn't a very commonly used language around here. Most of those who know it like it[citation needed], but some go :\
when they encounter its user-defined operators, saying they're too complicated.
However, they're governed by a very simple set of rules, outlined here. Their precedence depends on the first character. Here's the list for that (highest to lowest precedence):
* / %
+ -
:
= !
< >
&
^
|
(all letters)
So this
a + b ^? c less a ==> b | c
would be the same as this
((a + b) ^? c) less ((a ==> b) | c)
Your task is to turn such an expression (only infix applications) into a tree-like structure or a string with all the sub-expressions in parentheses.
Input
A string or multiple characters given as an argument to a function, read from STDIN, given as command-line arguments, or using one of the other default input methods. This string is the expression to be parsed.
Output
You could do one of the following, printed to STDOUT, returned from a function, or one of the other default output methods:
- The same string but with parentheses outside each sub-expression (the outermost expression may or may not be parenthesized). E.g.,
expr op expr2 op2 expr3
->(expr op expr2) op2 expr3
. If you wish, you may also parenthesize the atoms ((((expr) op (expr2)) op2 (expr3))
) - A multidimensional list, where each expression would broken up into the left argument, the operator/method, and the right argument. E.g.,
expr op expr2 op2 expr3
->[['expr','op','expr2'],'op2','expr3']
- Some tree-like structure equivalent to the above 2 representations. You get the idea.
Rules
- All operators used are binary, infix, and left-associative.
- Parsing goes from left to right.
- There will always be one or more spaces between arguments and operators.
- Operators may consist of any of the symbols mentioned above (
*/%+-:=!<>&^|
) and uppercase or lowercase letters([A-Za-z]
). They will be one or more characters. - Arguments to methods may be other expressions or alphabetical identifiers (
[A-Za-z]
). - This is code-golf, so shortest code wins!
Test cases
More coming soon
Input -> Output
a -- blah /\ foo -> a -- (blah /\ foo)
same ** fst *^ chr *& operators -> ((same ** fst) *^ chr) *& operators
Lots Of SpAceS // here -> Lots Of (SpAceS // here)
Not : confusing * At / ALL iS it -> (Not : ((confusing * At) / ALL)) iS it
This *isnot* valid ** Scala -> (This *isnot* valid) ** Scala
?
in your first example but it isn't listed in the precedence table above. Is that because it belongs to (characters not shown below)? Either way it's confusing, Perhaps adding?
as an example of (characters not shown below) would be clearer. Or something else if that's not the case. And then letters pop up at the end? Are they not characrters not shown below? Maybe regexs explicitly stating them all would be better. \$\endgroup\$ – Noodle9 Oct 4 '20 at 8:30