My input is a string, I want to validate that there is only one first-level block of code.
Examples :
{ abc } TRUE
{ a { bc }
Since this is in Javascript there's not really much to do, but please see the following regex:
/^{([^{}]*|{})*}$/
Where you copy ([^{}]*|{})*
and insert it between the last pair of curly brackets (rinse and repeat). Every duplication of this pattern allows another level of nesting between your elements. (This is a workaround for the lack of recursion in JS regex, required to solve nesting problems.)
Online Regex Demo
(\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*
Code for brackets
EDIT: I started writing the answer before JavaScript was specified. Will leave it as for the record as it fully explains the regex.
In short: In JavaScript I cannot think of a reliable solution. In other engines there are several options:
For solutions 2 (which anyhow won't work in JS either), I'll refer you to the example in this question
In Perl, PCRE (e.g. Notepad++, PHP, R) and the Matthew Barnett's regex
module for Python, you can use:
^({(?:[^{}]++|(?1))*})$
The idea is to match exactly one set of nested braces. Anything more makes the regex fail.
See what matches and fails in the Regex Demo.
Explanation
^
anchor asserts that we are at the beginning of the string{
match the opening brace(?: ... )*
zero or more times, we will...[^{}]++
match any chars that are not {
or }
|
(?1)
repeat the expression of subroutine 1}
match closing brace $
anchor asserts that we are at the end of the string. Therefore, In JavaScript what you need to do is strip out all the nested blocks until no nested blocks are left and then check whether there are still multiple blocks:
var r = input.replace(/(['"])(?:(?!\1|\\).|\\.)*\1|\/(?![*/])(?:[^\\/]|\\.)+\/[igm]*|\/\/[^\n]*(?:\n|$)|\/\*(?:[^*]|\*(?!\/))*\*\//gi, '');
if (r.split('{').length != r.split('}').length || r.indexOf('}') < r.indexOf('{')) {
// ERROR
continue;
}
while (r.match(/\{[^}]*\{[^{}]*\}/))
r = r.replace(/(\{[^}]*)\{[^{}]*\}/g, '$1');
if (r.match(/\}.*\{/)
// FALSE
else
// TRUE
Working JSFiddle
Be sure to make the regex in the while
and the regex in the replace
match the same otherwise this might result in infinite loops.
Updated to address ERROR cases and remove anything in comments, strings and regex-literals first after Unihedron asked.