or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

ast-types.mdcore-functions.mdindex.mdparsing.mdvalidation.mdvisitor.md

validation.mddocs/

0

# Regular Expression Validation

1

2

The RegExpValidator class provides syntax validation with optional detailed callbacks for each regex component during validation, without generating an AST.

3

4

## Capabilities

5

6

### RegExp Validator Class

7

8

Creates a validator instance with configurable options and optional callbacks for validation events.

9

10

```typescript { .api }

11

/**

12

* Regular expression validator that checks regex syntax compliance

13

*/

14

class RegExpValidator {

15

/**

16

* Initialize the validator with options

17

* @param options - Validator configuration options and callbacks

18

*/

19

constructor(options?: RegExpValidator.Options);

20

}

21

22

interface RegExpValidator.Options {

23

/** The flag to disable Annex B syntax. Default is false */

24

strict?: boolean;

25

/** ECMAScript version. Default is 2022 */

26

ecmaVersion?: EcmaVersion;

27

28

// Validation event callbacks (all optional)

29

onLiteralEnter?(start: number): void;

30

onLiteralLeave?(start: number, end: number): void;

31

onFlags?(start: number, end: number, global: boolean, ignoreCase: boolean, multiline: boolean, unicode: boolean, sticky: boolean, dotAll: boolean, hasIndices: boolean): void;

32

onPatternEnter?(start: number): void;

33

onPatternLeave?(start: number, end: number): void;

34

onDisjunctionEnter?(start: number): void;

35

onDisjunctionLeave?(start: number, end: number): void;

36

onAlternativeEnter?(start: number, index: number): void;

37

onAlternativeLeave?(start: number, end: number, index: number): void;

38

onGroupEnter?(start: number): void;

39

onGroupLeave?(start: number, end: number): void;

40

onCapturingGroupEnter?(start: number, name: string | null): void;

41

onCapturingGroupLeave?(start: number, end: number, name: string | null): void;

42

onQuantifier?(start: number, end: number, min: number, max: number, greedy: boolean): void;

43

onLookaroundAssertionEnter?(start: number, kind: "lookahead" | "lookbehind", negate: boolean): void;

44

onLookaroundAssertionLeave?(start: number, end: number, kind: "lookahead" | "lookbehind", negate: boolean): void;

45

onEdgeAssertion?(start: number, end: number, kind: "start" | "end"): void;

46

onWordBoundaryAssertion?(start: number, end: number, kind: "word", negate: boolean): void;

47

onAnyCharacterSet?(start: number, end: number, kind: "any"): void;

48

onEscapeCharacterSet?(start: number, end: number, kind: "digit" | "space" | "word", negate: boolean): void;

49

onUnicodePropertyCharacterSet?(start: number, end: number, kind: "property", key: string, value: string | null, negate: boolean): void;

50

onCharacter?(start: number, end: number, value: number): void;

51

onBackreference?(start: number, end: number, ref: number | string): void;

52

onCharacterClassEnter?(start: number, negate: boolean): void;

53

onCharacterClassLeave?(start: number, end: number, negate: boolean): void;

54

onCharacterClassRange?(start: number, end: number, min: number, max: number): void;

55

}

56

```

57

58

**Usage Examples:**

59

60

```typescript

61

import { RegExpValidator } from "regexpp";

62

63

// Create basic validator

64

const validator = new RegExpValidator();

65

66

// Create validator with callbacks to analyze regex structure

67

const analyticValidator = new RegExpValidator({

68

ecmaVersion: 2022,

69

onCapturingGroupEnter(start, name) {

70

console.log(`Found capturing group: ${name || 'unnamed'} at position ${start}`);

71

},

72

onQuantifier(start, end, min, max, greedy) {

73

console.log(`Found quantifier {${min},${max}} (greedy: ${greedy}) at ${start}-${end}`);

74

},

75

onUnicodePropertyCharacterSet(start, end, kind, key, value, negate) {

76

console.log(`Unicode property: \\${negate ? 'P' : 'p'}{${key}${value ? '=' + value : ''}} at ${start}-${end}`);

77

}

78

});

79

80

// Create strict validator (disables Annex B features)

81

const strictValidator = new RegExpValidator({

82

strict: true,

83

ecmaVersion: 2022

84

});

85

```

86

87

### Validate Literal

88

89

Validates a complete regular expression literal including pattern and flags.

90

91

```typescript { .api }

92

/**

93

* Validate a regular expression literal

94

* @param source - The source code to validate (e.g., "/abc/g")

95

* @param start - The start index in the source code. Default is 0

96

* @param end - The end index in the source code. Default is source.length

97

* @throws {RegExpSyntaxError} If the regex has invalid syntax

98

*/

99

validateLiteral(source: string, start?: number, end?: number): void;

100

```

101

102

**Usage Examples:**

103

104

```typescript

105

import { RegExpValidator } from "regexpp";

106

107

const validator = new RegExpValidator();

108

109

// Basic validation

110

try {

111

validator.validateLiteral("/[a-z]+/gi");

112

console.log("Valid regex literal");

113

} catch (error) {

114

console.log("Invalid regex:", error.message);

115

}

116

117

// Validate with callbacks

118

const callbackValidator = new RegExpValidator({

119

onFlags(start, end, global, ignoreCase, multiline, unicode, sticky, dotAll, hasIndices) {

120

console.log(`Flags: g=${global}, i=${ignoreCase}, m=${multiline}, u=${unicode}, y=${sticky}, s=${dotAll}, d=${hasIndices}`);

121

}

122

});

123

124

callbackValidator.validateLiteral("/test/gimsuyd");

125

126

// Validate substring

127

const source = "const regex = /\\d{2,4}/g;";

128

try {

129

validator.validateLiteral(source, 14, 24); // Just the "/\\d{2,4}/g" part

130

console.log("Extracted regex is valid");

131

} catch (error) {

132

console.log("Invalid regex syntax");

133

}

134

```

135

136

### Validate Pattern

137

138

Validates just the pattern part of a regular expression (without delimiters and flags).

139

140

```typescript { .api }

141

/**

142

* Validate a regular expression pattern

143

* @param source - The source code to validate (e.g., "abc")

144

* @param start - The start index in the source code. Default is 0

145

* @param end - The end index in the source code. Default is source.length

146

* @param uFlag - The flag to enable Unicode mode

147

* @throws {RegExpSyntaxError} If the pattern has invalid syntax

148

*/

149

validatePattern(source: string, start?: number, end?: number, uFlag?: boolean): void;

150

```

151

152

**Usage Examples:**

153

154

```typescript

155

import { RegExpValidator } from "regexpp";

156

157

const validator = new RegExpValidator();

158

159

// Validate simple pattern

160

try {

161

validator.validatePattern("abc");

162

console.log("Valid pattern");

163

} catch (error) {

164

console.log("Invalid pattern:", error.message);

165

}

166

167

// Validate with Unicode flag

168

try {

169

validator.validatePattern("\\p{Letter}+", 0, undefined, true);

170

console.log("Valid Unicode pattern");

171

} catch (error) {

172

console.log("Invalid Unicode pattern");

173

}

174

175

// Validate with callbacks

176

const patternValidator = new RegExpValidator({

177

onCharacterClassEnter(start, negate) {

178

console.log(`Character class ${negate ? 'negated' : 'normal'} at position ${start}`);

179

}

180

});

181

182

patternValidator.validatePattern("[^a-z]+");

183

```

184

185

### Validate Flags

186

187

Validates just the flags part of a regular expression.

188

189

```typescript { .api }

190

/**

191

* Validate regular expression flags

192

* @param source - The source code to validate (e.g., "gim")

193

* @param start - The start index in the source code. Default is 0

194

* @param end - The end index in the source code. Default is source.length

195

* @throws {RegExpSyntaxError} If the flags are invalid

196

*/

197

validateFlags(source: string, start?: number, end?: number): void;

198

```

199

200

**Usage Examples:**

201

202

```typescript

203

import { RegExpValidator } from "regexpp";

204

205

const validator = new RegExpValidator();

206

207

// Validate flags

208

try {

209

validator.validateFlags("gim");

210

console.log("Valid flags");

211

} catch (error) {

212

console.log("Invalid flags:", error.message);

213

}

214

215

// Invalid flags will throw

216

try {

217

validator.validateFlags("gix"); // 'x' is not a valid flag

218

} catch (error) {

219

console.log("Error:", error.message);

220

}

221

222

// Duplicate flags will throw

223

try {

224

validator.validateFlags("gg"); // Duplicate 'g' flag

225

} catch (error) {

226

console.log("Error:", error.message);

227

}

228

```

229

230

## Advanced Validation with Callbacks

231

232

The validator's callback system allows detailed analysis during validation:

233

234

```typescript

235

import { RegExpValidator } from "regexpp";

236

237

// Comprehensive analysis validator

238

const analyzer = new RegExpValidator({

239

ecmaVersion: 2022,

240

241

onPatternEnter(start) {

242

console.log(`Starting pattern analysis at position ${start}`);

243

},

244

245

onCapturingGroupEnter(start, name) {

246

if (name) {

247

console.log(`Named capture group '${name}' at ${start}`);

248

} else {

249

console.log(`Unnamed capture group at ${start}`);

250

}

251

},

252

253

onQuantifier(start, end, min, max, greedy) {

254

const type = min === max ? 'exact' : min === 0 && max === Infinity ? 'zero-or-more' : 'range';

255

console.log(`Quantifier: ${type} {${min},${max === Infinity ? '∞' : max}} ${greedy ? 'greedy' : 'lazy'}`);

256

},

257

258

onBackreference(start, end, ref) {

259

console.log(`Backreference to ${typeof ref === 'string' ? `'${ref}'` : `group ${ref}`} at ${start}-${end}`);

260

}

261

});

262

263

// Analyze a complex regex

264

analyzer.validateLiteral("/(?<year>\\d{4})-(?<month>\\d{2})\\k<year>/g");

265

```

266

267

## Error Handling

268

269

All validation methods may throw RegExpSyntaxError for invalid syntax:

270

271

```typescript

272

import { RegExpValidator } from "regexpp";

273

274

const validator = new RegExpValidator();

275

276

try {

277

validator.validateLiteral("/[z-a]/"); // Invalid character class range

278

} catch (error) {

279

console.log(error.name); // "RegExpSyntaxError"

280

console.log(error.message); // Detailed error message

281

console.log(error.index); // Position where error occurred

282

}

283

284

// Version-specific validation

285

const es2017Validator = new RegExpValidator({ ecmaVersion: 2017 });

286

287

try {

288

es2017Validator.validatePattern("(?<=\\w)\\d+"); // Lookbehind requires ES2018+

289

} catch (error) {

290

console.log("Feature not supported in ES2017");

291

}

292

```

293

294

## Types

295

296

```typescript { .api }

297

type EcmaVersion = 5 | 2015 | 2016 | 2017 | 2018 | 2019 | 2020 | 2021 | 2022;

298

299

// Callback function types

300

type ValidationCallback = (start: number, end: number, ...args: any[]) => void;

301

302

// Error type thrown by validation methods

303

class RegExpSyntaxError extends SyntaxError {

304

index: number;

305

constructor(source: string, uFlag: boolean, index: number, message: string);

306

}

307

```