'Working with regex and parentheses to return 3 groups: operand1/operator/operand2

I'm trying to use a Regex in JavaScript which matches a string and returns 3 groups: operand1, operator, and operand2. For example dissecting an exponent clause:

const EXPONENT_REGEX = /(\S+)\s*([\^])\s*(\S+)/
const inpStr = '5 ^ 2 + 10 * 2'
inpStr.match(EXPONENT_REGEX) 
// Returns: ['5 ^ 2', '5', '^', '2'] 
// i.e. [Matched Clause, Operand1, Operator, Operand2] 

When trying a similar approach to handle parentheses clauses however, and possible nested parentheses- I've been unable to find the right arrangement of escape square brackets and parentheses for grouping to return me those 3 values. Consider:

const PARENTHESES_REGEX = /\([^\(\)]*\)/
const inpStr = '5 ^ 2 + 10 * (10 - (4 + (2 + 1))'
inpStr.match(PARENTHESES_REGEX)

Currently this does not return any groups, but does match '(2 + 1)'. How might I structure this to return those same 3 groups as the first example? Here that would look like:

['2 + 1', '2', '+', '1']



Solution 1:[1]

Use

const PARENTHESES_REGEX = /\((-?\d*\.?\d+)\s*([-+\/*])\s*(\d*\.?\d+)\)/g
const inpStr = '5 ^ 2 + 10 * (10 - (4 + (2 + 1))'
console.log([...inpStr.matchAll(PARENTHESES_REGEX)])

EXPLANATION

--------------------------------------------------------------------------------
  \(                       '('
--------------------------------------------------------------------------------
  (                        group and capture to \1:
--------------------------------------------------------------------------------
    -?                       '-' (optional (matching the most amount
                             possible))
--------------------------------------------------------------------------------
    \d*                      digits (0-9) (0 or more times (matching
                             the most amount possible))
--------------------------------------------------------------------------------
    \.?                      '.' (optional (matching the most amount
                             possible))
--------------------------------------------------------------------------------
    \d+                      digits (0-9) (1 or more times (matching
                             the most amount possible))
--------------------------------------------------------------------------------
  )                        end of \1
--------------------------------------------------------------------------------
  \s*                      whitespace (\n, \r, \t, \f, and " ") (0 or
                           more times (matching the most amount
                           possible))
--------------------------------------------------------------------------------
  (                        group and capture to \2:
--------------------------------------------------------------------------------
    [-+\/*]                  any character of: '-', '+', '\/', '*'
--------------------------------------------------------------------------------
  )                        end of \2
--------------------------------------------------------------------------------
  \s*                      whitespace (\n, \r, \t, \f, and " ") (0 or
                           more times (matching the most amount
                           possible))
--------------------------------------------------------------------------------
  (                        group and capture to \3:
--------------------------------------------------------------------------------
    \d*                      digits (0-9) (0 or more times (matching
                             the most amount possible))
--------------------------------------------------------------------------------
    \.?                      '.' (optional (matching the most amount
                             possible))
--------------------------------------------------------------------------------
    \d+                      digits (0-9) (1 or more times (matching
                             the most amount possible))
--------------------------------------------------------------------------------
  )                        end of \3
--------------------------------------------------------------------------------
  \)                       ')'

Results: (4) ['(2 + 1)', '2', '+', '1', index: 24, input: '5 ^ 2 + 10 * (10 - (4 + (2 + 1))', groups: undefined]

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Ryszard Czech