
Security News
ECMAScript 2025 Finalized with Iterator Helpers, Set Methods, RegExp.escape, and More
ECMAScript 2025 introduces Iterator Helpers, Set methods, JSON modules, and more in its latest spec update approved by Ecma in June 2025.
clarity-pattern-parser
Advanced tools
A powerful pattern matching and parsing library that provides a flexible grammar for defining complex patterns. Perfect for building parsers, validators, and text processing tools.
Try it online! 🚀 Open in Playground
npm install clarity-pattern-parser
import { patterns } from "clarity-pattern-parser";
// Define patterns using grammar
const { fullName } = patterns`
first-name = "John"
last-name = "Doe"
space = /\s+/
full-name = first-name + space + last-name
`;
// Execute pattern
const result = fullName.exec("John Doe");
console.log(result.ast?.value); // "John Doe"
import { Literal, Sequence } from "clarity-pattern-parser";
// Create patterns directly
const firstName = new Literal("first-name", "John");
const space = new Literal("space", " ");
const lastName = new Literal("last-name", "Doe");
const fullName = new Sequence("full-name", [firstName, space, lastName]);
// Execute pattern
const result = fullName.exec("John Doe");
console.log(result.ast?.value); // "John Doe"
Try Clarity Pattern Parser in your browser with our interactive playground:
The playground allows you to:
This document describes the grammar features supported by the Clarity Pattern Parser.
Define literal string patterns using double quotes:
name = "John"
Escaped characters are supported in literals:
\n
- newline\r
- carriage return\t
- tab\b
- backspace\f
- form feed\v
- vertical tab\0
- null character\x00
- hex character\u0000
- unicode character\"
- escaped quote\\
- escaped backslashDefine regex patterns using forward slashes:
name = /\w/
Match one of multiple patterns using the |
operator. This is used for simple alternatives where order doesn't matter:
names = john | jane
Expression patterns also use the |
operator but are used for defining operator precedence in expressions. The order of alternatives determines precedence, with earlier alternatives having higher precedence. By default, operators are left-associative.
Example of an arithmetic expression grammar:
prefix-operators = "+" | "-"
prefix-expression = prefix-operators + expression
postfix-operators = "++" | "--"
postfix-expression = expression + postfix-operators
add-sub-operators = "+" | "-"
add-sub-expression = expression + add-sub-operators + expression
mul-div-operators = "*" | "/"
mul-div-expression = expression + mul-div-operators + expression
expression = prefix-expression | mul-div-expression | add-sub-expression | postfix-expression
Repeat a pattern one or more times using +
:
digits = (digit)+
Repeat a pattern zero or more times using *
:
digits = (digit)*
Specify exact repetition counts using curly braces:
{n}
- Exactly n times: (pattern){3}
{n,}
- At least n times: (pattern){1,}
{,n}
- At most n times: (pattern){,3}
{n,m}
- Between n and m times: (pattern){1,3}
Repeat patterns with a divider between occurrences:
digits = (digit, comma){3}
Add trim
keyword to trim the divider from the end:
digits = (digit, comma trim)+
Import patterns from other files:
import { pattern-name } from "path/to/file.cpat"
Import with custom parameters:
import { pattern } from "file.cpat" with params {
custom-param = "value"
}
Declare parameters that can be passed to the grammar:
use params {
param-name
}
Specify default values for parameters:
use params {
param = default-value
}
Specify tokens for a pattern:
@tokens([" "])
spaces = /\s+/
Support for custom decorators with various argument types:
@decorator() // No arguments
@decorator(["value"]) // Array argument
@decorator({"prop": value}) // Object argument
Add comments using the #
symbol:
# This is a comment
pattern = "value"
Reference other patterns by name:
pattern1 = "value"
pattern2 = pattern1
Import patterns with aliases:
import { original as alias } from "file.cpat"
Patterns can be defined inline using string templates. This allows for quick pattern definition and testing without creating separate files.
const { fullName } = patterns`
first-name = "John"
last-name = "Doe"
space = /\s+/
full-name = first-name + space + last-name
`;
const result = fullName.exec("John Doe");
// result.ast.value will be "John Doe"
const { body } = patterns`
tag-name = /[a-zA-Z_-]+[a-zA-Z0-9_-]*/
ws = /\s+/
opening-tag = "<" + tag-name + ws? + ">"
closing-tag = "</" + tag-name + ws? + ">"
child = ws? + element + ws?
children = (child)*
element = opening-tag + children + closing-tag
body = ws? + element + ws?
`;
const result = body.exec(`
<div>
<div></div>
<div></div>
</div>
`, true);
// Clean up spaces from the AST
result?.ast?.findAll(n => n.name.includes("ws")).forEach(n => n.remove());
// result.ast.value will be "<div><div></div><div></div></div>"
While the grammar provides a convenient way to define patterns, you can also use the Pattern classes directly for more control and flexibility.
import { Literal } from "clarity-pattern-parser";
const firstName = new Literal("first-name", "John");
const result = firstName.exec("John");
// result.ast.value will be "John"
import { Regex } from "clarity-pattern-parser";
const digits = new Regex("digits", "\\d+");
const result = digits.exec("123");
// result.ast.value will be "123"
import { Sequence, Literal } from "clarity-pattern-parser";
const firstName = new Literal("first-name", "John");
const space = new Literal("space", " ");
const lastName = new Literal("last-name", "Doe");
const fullName = new Sequence("full-name", [firstName, space, lastName]);
const result = fullName.exec("John Doe");
// result.ast.value will be "John Doe"
import { Options, Literal } from "clarity-pattern-parser";
const john = new Literal("john", "John");
const jane = new Literal("jane", "Jane");
const names = new Options("names", [john, jane]);
const result = names.exec("Jane");
// result.ast.value will be "Jane"
import { Expression, Literal } from "clarity-pattern-parser";
const a = new Literal("a", "a");
const b = new Literal("b", "b");
const c = new Literal("c", "c");
const expression = new Expression("expression", [a, b, c]);
const result = expression.exec("a ? b : c");
// result.ast.value will be "a ? b : c"
import { Context, Literal } from "clarity-pattern-parser";
const name = new Literal("name", "John");
const context = new Context("name-context", name);
const result = context.exec("John");
// result.ast.value will be "John"
import { Reference, Literal, Sequence } from "clarity-pattern-parser";
const name = new Literal("name", "John");
const reference = new Reference("name-ref", name);
const pattern = new Sequence("pattern", [reference]);
const result = pattern.exec("John");
// result.ast.value will be "John"
Pattern execution returns a ParseResult
that includes the AST and any error information:
const result = pattern.exec("some text");
if (result.error) {
console.error(result.error.message);
console.error(result.error.expected);
console.error(result.error.position);
} else {
console.log(result.ast?.value);
}
The AST (Abstract Syntax Tree) returned by pattern execution can be manipulated:
const result = pattern.exec("some text");
if (result.ast) {
// Find all nodes with a specific name
const nodes = result.ast.findAll(n => n.name === "space");
// Remove nodes
nodes.forEach(n => n.remove());
// Get the final value
const value = result.ast.value;
}
You can create custom patterns by extending the base Pattern
class:
import { Pattern } from "clarity-pattern-parser";
class CustomPattern extends Pattern {
constructor(name: string) {
super(name);
}
exec(text: string) {
// Custom pattern implementation
}
}
test()
instead of exec()
when you only need to check if a pattern matchesReference
for recursive patterns instead of direct recursionEnable debug mode to get detailed information about pattern execution:
const result = pattern.exec("some text", true);
// Debug information will be available in result.debug
Pattern execution returns a ParseResult
that includes error information:
const result = pattern.exec("invalid text");
if (result.error) {
console.error(result.error.message);
console.error(result.error.expected);
console.error(result.error.position);
}
const { json } = patterns`
# Basic JSON grammar
ws = /\s+/
string = /"[^"]*"/
number = /-?\d+(\.\d+)?/
boolean = "true" | "false"
null = "null"
value = string | number | boolean | null | array | object
array-items = (value, /\s*,\s*/)+
array = "[" +ws? + array-items? + ws? + "]"
object-property = string + ws? + ":" + ws? + value
object-properties = (object-property, /\s*,\s*/ trim)+
object = "{" + ws? + object-properties? + ws? + "}"
json = ws? + value + ws?
`;
const { html } = patterns`
# Basic HTML grammar
ws = /\s+/
tag-name = /[a-zA-Z_-]+[a-zA-Z0-9_-]*/
attribute-name = /[a-zA-Z_-]+[a-zA-Z0-9_-]*/
attribute-value = /"[^"]*"/
value-attribute = attribute-name + "=" + attribute-value
bool-attribute = attribute-name
attribute = value-attribute | bool-attribute
attributes = (attribute, ws)*
opening-tag = "<" + ws? + tag-name + ws? + attributes? + ">"
closing-tag = "</" + ws? + tag-name + ws? + ">"
text = /[^<]+/
child = text | element
children = (child, /\s*/)+
element = opening-tag + children? + closing-tag
html = ws? + element + ws?
`;
This project is licensed under the MIT License - see the LICENSE file for details.
FAQs
Parsing Library for Typescript and Javascript.
The npm package clarity-pattern-parser receives a total of 5,200 weekly downloads. As such, clarity-pattern-parser popularity was classified as popular.
We found that clarity-pattern-parser demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
ECMAScript 2025 introduces Iterator Helpers, Set methods, JSON modules, and more in its latest spec update approved by Ecma in June 2025.
Security News
A new Node.js homepage button linking to paid support for EOL versions has sparked a heated discussion among contributors and the wider community.
Research
North Korean threat actors linked to the Contagious Interview campaign return with 35 new malicious npm packages using a stealthy multi-stage malware loader.