0

I need to validate a string for given specifications:

const string = 'd(iig(i)), d(iitm), d' // is valid

Mainly the string represents one or multiple blocks of d, which can be without brackets or empty brackets. Each block is separated by comma and an optional space.

Inside of this block there can be g, i, t or m. Only g can optionaly open new bracket.

I started with this regex:

if (!/^[dgitm, ()]*$/.test(string)) {
  throw Error('Pattern has invalid character')
}

But I don't know how to treat these specifications:

  1. Each block has to be separated by a comma (optinal with space)
  2. Space is only allowed (optional) between d-blocks
  3. d and g could have following brackets; i, t and m should not have following brackets
  4. d is never inside any bracket

Valid

dd(ii)
d(i),d(g)
d(g(iig))
d(g(iig(i)))

Invalid

d(g(d))    // no nested d
d(x)       // invalid character
d(i())     // no brackets for i (only d or g)
d(ii)d(ii) // missing comma
i          // missing first level d

Update

Removed the spec for balanced brackets, as this can't be tested by regEx.

user3142695
  • 11,619
  • 29
  • 119
  • 238

1 Answers1

2
^d+(\((g\(|[git](?!\()|\))+)*(,d+(\((g\(|[git](?!\()|\))+)*)*$

It can be tested here.

Explanation:

^d+                                 The input must start with some 'd's (m>=1 times)

// First parenthesis' content:
(\((g\(|[git](?!\()|\))+)*          The following can appear n>=0 times:
                                    '(', then the following can appear p>=1 times:
                                        'g', then one of the following:
                                            - 'g('
                                            - ')'
                                            - 'g'/'i'/'t' - without a '(' after them
                                              (using negative lookahead)

// Every other element (optional):
(,d+(\((g\(|[git](?!\()|\))+)*)*    Starts with a ',d', ',dd' or ',ddd', etc.
                                    then the same as the first parenthesis' content

As I mentioned in the comments, you can't validate brackets with regex. However you can either implement an existing algorithm for that, or get a sense of initial validation by comparing the amount of opening and closing parenthesis (which obviously should be equal).

EDIT: Thank you, @anubhava, for the correction

GalAbra
  • 4,282
  • 4
  • 18
  • 34