I am a Wolfram Language/Mathematica beginner and trying to convert STEP ISO10303 commands into geometrical regions. A simple command looks like


I tried with String commands to convert it into a valid ToExpression string like


allowing then to convert it with Rules into geometrical objects.

I managed to get a first prototype running but struggled finding a generic way of converting nested parentheses.

As I am a mediocre Perl programmer I would use the recipe https://stackoverflow.com/questions/4445674/can-i-use-perl-regular-expressions-to-match-balanced-text but I could not find information if Mathematica regex allows using longest match without backtracking and reference to sub-pattern?

Literature says that one either needs recursive regex usage or stack implementation when trying to parse nested objects.

Any help on how to tackle this problem is much appreciated.

Regards Markus


4 Answers 4


I'd do the minimum necessary to make a legitimate, unambiguous Mathematica expression, and then let Mathematica rewrite it.

stepexpr[s_] := ToExpression[StringReplace[s, {"(" -> " dummy[", ")" -> "]"}]] /.
op_Symbol dummy[args__] -> op[args] /. dummy -> List

This replaces () expressions with a dummy[] function in the string, making a legal expression. Then, in Mathematica, it transforms op dummy[args] into op[args]. Finally, it makes Lists of the remaining dummy functions.

(* {vector[a, {b, c}], line[d, {e, f}]} *)
  • $\begingroup$ Very clever! I am really impressed by the power of Mathematica. It is good that I can learn from all of you. Thanks for sharing. $\endgroup$
    – markilux
    Commented Jan 8, 2018 at 20:00
  • $\begingroup$ I saw another solution using Times=Sequence and tried to follow up on it with inline Block[{Times = Sequence}, step = StringReplace["(vector(a,(b,c)))", {"(" -> "{", ")" -> "}"}] // ToExpression; step /. {w_, c_} :> w[c] ] Unfortunately I did not manage to get this solution work with a list of commands like shown in my question. I experimented with Apply working on a pair of list but did not manage to get it run. May be you can show me how to do this. $\endgroup$
    – markilux
    Commented Jan 8, 2018 at 20:06
  • $\begingroup$ Sequence is a rather peculiar object, and I don't know how to employ it to do what you want. $\endgroup$
    – John Doty
    Commented Jan 9, 2018 at 21:12

In your example you need [] if and only if two letters precede.
If that fact extends to the generel case, then

ToExpression[With[{s1 = StringReplace[string, {
  a_ ~~ b_ ~~ "(" /; LetterQ[a] && LetterQ[b] :> a <> b <> "[",
  "(" -> "{"}]},
  StringCases[s1, {"[", "{"}] /. {"{" -> "}", "[" -> "]"},
  StringPosition[s1, ")"]]]]
{vector[a, {b, c}], line[d, {e, f}]}

In the case of that example:

str = "(vector(a,(b,c)),line(d,(e,f)))";
StringCases[str, {
  "vector(" ~~ Shortest[arg1__] ~~ ",(" ~~ Shortest[arg2__] ~~ "," ~~ Shortest[arg3__] ~~ "))" :> vector[arg1, {arg2, arg3}],
  "line(" ~~ Shortest[arg1__] ~~ ",(" ~~ Shortest[arg2__] ~~ "," ~~ Shortest[arg3__] ~~ "))" :> line[arg1, {arg2, arg3}]

{vector["a", {"b", "c"}], line["d", {"e", "f"}]}

Feel free to tell me if this is not general enough or if there is another problem.

If you have lists of varying length so that you cannot encode it directly in the pattern:

 "f(" ~~ args__ ~~ ")" :> StringSplit[args, ","]

{{"a", "b", "c", "d"}}


Starting from this great answer we can do this in two steps using recursive regular expressions:

str = "(vector(a,(b,c,vector(a,(b,c)))),line(d,(e,f)))";
sqBrPos = StringPosition[str, 
                WordBoundary ~~ RegularExpression@"(?P<a>\\(([^\\(\\)]|(?P>a))*\\))"];
str2 = StringReplacePart[StringReplacePart[str, "[", {#1, #1} & @@@ sqBrPos], 
                                                "]", {#2, #2} & @@@ sqBrPos]
curBrPos = StringPosition[str2, RegularExpression@"(?P<a>\\(([^\\(\\)]|(?P>a))*\\))"];
str3 = StringReplacePart[StringReplacePart[str2, "{", {#1, #1} & @@@ curBrPos], 
                                                 "}", {#2, #2} & @@@ curBrPos]
ToExpression[str3, InputForm, Hold]


Hold[{vector[a, {b, c, vector[a, {b, c}]}], line[d, {e, f}]}]

Strongly related:

  • $\begingroup$ Good to know that recursive regular expressions work. Do you know which regex engine is used in Mathematica as the Documentation Center is not stating that one can use ?P It looks to me like Perl with the fact that each backslash has to be escaped in Mathemitca. $\endgroup$
    – markilux
    Commented Jan 8, 2018 at 19:59
  • $\begingroup$ @MarkusSonderegger Mathematica uses the PCRE library, which currently (starting from Mathematica version 10.1) supports different styles for backreferences. You should read the official PCRE docs for the syntax. And yes, you must additionally escape every backslash inside of RegularExpression. $\endgroup$ Commented Jan 8, 2018 at 20:14
  • $\begingroup$ @MarkusSonderegger About escaping in RegularExpression you can be interested in this answer. $\endgroup$ Commented Jan 10, 2018 at 5:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.