An object-oriented language for parsing and pattern matching based on parsing expression grammars
npx @tessl/cli install tessl/npm-ohm-js@17.2.0Ohm is a parsing toolkit consisting of a library and domain-specific language for creating parsers, interpreters, and compilers. It's based on parsing expression grammars (PEGs) with full support for left-recursive rules, object-oriented grammar extension, and modular semantic actions that are completely separated from grammars.
npm install ohm-jsimport { grammar, grammars, pexprs, ohmGrammar, version } from "ohm-js";For TypeScript with full type support:
import {
grammar,
grammars,
Grammar,
Semantics,
MatchResult,
Matcher,
Interval,
pexprs,
ohmGrammar,
ExperimentalIndentationSensitive,
version
} from "ohm-js";CommonJS:
const { grammar, grammars, pexprs, ohmGrammar, version } = require("ohm-js");Extras module (utilities):
import { toAST, getLineAndColumnMessage, VisitorFamily, extractExamples } from "ohm-js/extras";import { grammar } from "ohm-js";
// Define a simple arithmetic grammar
const arithmeticGrammar = grammar(`
Arithmetic {
Exp = AddExp
AddExp = MulExp ("+" MulExp | "-" MulExp)*
MulExp = PriExp ("*" PriExp | "/" PriExp)*
PriExp = "(" Exp ")" | number
number = digit+
}
`);
// Parse an expression
const match = arithmeticGrammar.match("2 + 3 * 4");
if (match.succeeded()) {
console.log("Parse successful!");
} else {
console.error("Parse failed:", match.message);
}
// Create semantic actions
const semantics = arithmeticGrammar.createSemantics().addOperation('eval', {
Exp(e) { return e.eval(); },
AddExp(expr) {
return expr.children.length === 1
? expr.children[0].eval()
: // Handle addition/subtraction operations
this.sourceString; // Simplified
},
number(digits) {
return parseInt(this.sourceString);
}
});
// Evaluate the expression
const result = semantics(match).eval();Ohm is built around several key components:
Grammar, Namespace)MatchResult, Matcher)Semantics, Node)pexprs)Core functionality for creating and managing Ohm grammars from source definitions.
function grammar(source: string, namespace?: Namespace): Grammar;
function grammars(source: string, namespace?: Namespace): Namespace;
interface Namespace {
[index: string]: Grammar;
}Grammar parsing capabilities with support for incremental parsing and detailed error reporting.
interface Grammar {
name: string;
superGrammar: Grammar;
rules: {[ruleName: string]: RuleInfo};
match(input: string, startRule?: string): MatchResult;
matcher(): Matcher;
trace(input: string, startRule?: string): Object;
isBuiltIn(): boolean;
createSemantics(): Semantics;
extendSemantics(superSemantics: Semantics): Semantics;
}
interface MatchResult {
succeeded(): boolean;
failed(): boolean;
message?: string;
shortMessage?: string;
getInterval(): Interval;
}System for defining and executing semantic actions on parse results, completely separated from grammar definitions.
interface Semantics {
(match: MatchResult): Dict;
addOperation<T>(name: string, actionDict: ActionDict<T>): Semantics;
addAttribute<T>(name: string, actionDict: ActionDict<T>): Semantics;
extendOperation<T>(name: string, actionDict: ActionDict<T>): Semantics;
extendAttribute<T>(name: string, actionDict: ActionDict<T>): Semantics;
}
interface ActionDict<T> extends BaseActionDict<T> {
[index: string]: Action<T> | undefined;
}
type Action<T> = (this: Node, ...args: Node[]) => T;Low-level parsing expression classes that form the building blocks of Ohm grammars.
const pexprs: {
PExpr: typeof PExpr;
Terminal: typeof Terminal;
Range: typeof Range;
Param: typeof Param;
Alt: typeof Alt;
Extend: typeof Extend;
Splice: typeof Splice;
Seq: typeof Seq;
Iter: typeof Iter;
Star: typeof Star;
Plus: typeof Plus;
Opt: typeof Opt;
Not: typeof Not;
Lookahead: typeof Lookahead;
Lex: typeof Lex;
Apply: typeof Apply;
UnicodeChar: typeof UnicodeChar;
CaseInsensitiveTerminal: typeof CaseInsensitiveTerminal;
any: PExpr;
end: PExpr;
};Additional utilities for error reporting, AST conversion, and advanced tree traversal patterns.
// Error reporting utilities
function getLineAndColumnMessage(str: string, offset: number, ...ranges: number[][]): string;
function getLineAndColumn(str: string, offset: number): LineAndColumnInfo;
// AST conversion
function toAST(matchResult: MatchResult, mapping?: {}): {};
function semanticsForToAST(g: Grammar): Semantics;
// Example extraction from grammar comments
function extractExamples(grammarsDef: string): Example[];
// Visitor pattern for tree traversal
class VisitorFamily {
constructor(config: VisitorConfig);
addOperation(signature: string, actions: {}): VisitorFamily;
wrap(thing: any): any;
}const ohmGrammar: Grammar;
const ExperimentalIndentationSensitive: Grammar;
const version: string;ohmGrammar: The meta-grammar used to parse Ohm grammar definitionsExperimentalIndentationSensitive: Experimental grammar for indentation-sensitive languagesversion: Package version string