0

I'd like to apply a regexp code to the part of a string that is before and/or after a specific character, and that character must be outside parenthesis.

To be more specific, I am coding a website (in React.JS) showing logical calculation, and I want to remove the first and last parenthesis before and after the main logical operator. For example, in the string:

"((p∧r)∧(q∧r))∧(p∧q)"

I want to get only: "(p∧r)∧(q∧r)" and "p∧q".

That means I want to get all the character before and after the only "∧" outside of any parenthesis, and I want to remove the first opening parenthesis and the last closing parenthesis of the two string. (The result could be an array with the part before and after for example.) I am already able to remove the first parenthis with this code :

str.replace(/(\()(.*)(\))/, "$2");

But that code is applied to the whole string right now.

So how do I apply this code to the two parts before and after the only "∧" outside parenthesis ? If possible I'd prefer a code only in regexp, but a JavaScript part would do. Thanks by advance.

u-ways
  • 6,136
  • 5
  • 31
  • 47
muleet
  • 1
  • 2
  • 1
    Please provide a clear input example and the desired output. – Pedro Lobito Aug 27 '18 at 18:40
  • Is it possible to have more than 2 conditions? for example: `(a^a) ^ (b^b) ^ (c^c)`? – Julio Aug 27 '18 at 18:57
  • My website has to show an infinity of possible combination of character, that all obeys a certain pattern. It will never have more than one operator outside parenthesis, and It will only have something before and after that operator. Here are other examples : p∧(p∧q) must return ["p", "p∧q"]. (p⊃(p∧q))∧(p∧((p∧p)∧q)) must return ["p⊃(p∧q)", "p∧((p∧p)∧q)"]. – muleet Aug 27 '18 at 19:10
  • Julio > There can never be two operators next to each other, and a letter or a set of parenthesis cannot be adjacent to two operators. My code already manage all that. – muleet Aug 27 '18 at 19:13
  • I mean, in all your examples you always return 2 *"pieces"*. Is it possible to return any other number than 2? For example `(a^x)^(b^y)^(c^z)` would return `['(a^x)','(b^y)','(c^z)']`? Is that correct or you always work with **only** 2 expressions combined with some logical operator? – Julio Aug 27 '18 at 19:20
  • Yes there is always only 2 expressions at the end. (It's all aristotelician stuff by the way, I didn't come up personally with the rules I am describing.) Something like your examples, or simply p∧p∧p or p∧q∧r or p⊃q∧r would simply be weird to interpretate logically. So they are never part of my website and must not be taken into account here. – muleet Aug 27 '18 at 19:24
  • @mulet, If you are still interested with this, you may ask a similar question but then not asking for a regex. I coded a solution with plain javascript and recursion that should work. But I cannot post it here because the question has been closed. – Julio Aug 28 '18 at 11:16
  • Hey thanks Julio ! I just saw your message. I think I succeeded to do a good javascript code about it, on my own (not entirely sure if it works for every possibility, and it's probably too long and too ugly) so I'd be happy to see your solution. Could you post it on pastebin and post the link here ? Thanks in advance. – muleet Aug 28 '18 at 14:08
  • @muleet, uploaded here: http://jsfiddle.net/74exhz0b/5/. See if it works for you – Julio Aug 28 '18 at 14:54
  • I think my code will be fine for my site but thank you very much anyway ! – muleet Aug 28 '18 at 16:53

2 Answers2

1

You will not be able to do this in pure regex, this is similar of trying to parse HTML with regex. in short, it is not possible (and have been answered many time over in all possible way)

So you will need javascript. To do this in javascript will not be simple, as you will need to parse the entire string to find "^-who-are-not-in-parenthese".

I would first check if there is some parser for mathematical operation or other who already exist and could be adapted for your need.

If you do not find something, you will need to create yourself.

You could do it with a loop passing character by character, having a counter for the indentation level of parenthesis, and a tree-like data structure as an output.

you could also use regex to find the last level of indentation and creating a bottom-up parser. you find all the innerest parenthesis group, saved them, and replace them with a special identifier character. you can then redo the operation to find the now innerest parenthesis group, check if there is special character in them and place them in the tree (as parent of the element identified by the character.)

once you have your tree structure (in one way or another), the root and the first level of element should be what you want.

Félix Brunet
  • 1,993
  • 1
  • 18
  • 22
1

You could do it this way:

// your string
const fixMe = "((p∧r)∧(q∧r))^(p∧q)";

// Separate double paren items from single paren items
const parts = fixMe.match(/\(\(.*\)\)|\(.*\)/g).map(
  // Get rid of leading and following parens
  item => item.replace(/^\(|\)$/g, '')
);

However, note: this solution is not very flexible. Better might some sort of recursive parenthesis lookup where each loop keeps an accounting of nesting level, etc...

jsplaine
  • 612
  • 5
  • 16
  • you are right, if you have a bounded number of parenthese level, a similar regex could work and be far simpler than creating a parser. – Félix Brunet Aug 27 '18 at 18:51
  • Thanks for your code but that is not enough for my need. There are times where what is adjacent to the main logical operator is only one character (like "p") and times where then can be like ten layer of parenthesis (even though that would be very uncommonn). – muleet 12 mins ago – muleet Aug 27 '18 at 19:52