Install & Compatibility
Where this runs
tested against v? · npm install
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslnode 18–226 runs
build_error
glibcnode 18–226 runs
build_error
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
lop.Parser
✓ import { Parser } from 'lop';
✗ const lop = require('lop'); const Parser = lop.Parser;
lop does not have a default export; use named import or destructure from require.
RegexTokeniser
✓ import { RegexTokeniser } from 'lop';
✗ const RegexTokeniser = require('lop').RegexTokeniser;
Named export; same pattern as other symbols.
rules
✓ import { rules } from 'lop';
✗ const { rules } = require('lop');
rules object contains combinators like tokenOfType, sequence, firstOf.
StringSource
✓ import { StringSource } from 'lop';
✗ const StringSource = require('lop').StringSource;
Used for custom tokeniser input.
default (none)
✓ import * as lop from 'lop';
✗ import lop from 'lop';
No default export; namespace import works.
Demonstrates a simple parser using lop with a regex tokeniser and parser combinators, including handling of cut and custom token types.
import { Parser, rules, tokenOfType, token, sequence, firstOf, rule } from 'lop';
import { RegexTokeniser } from 'lop';
// Define tokeniser
const tokeniser = new RegexTokeniser([
{ name: 'integer', regex: /(\d+)/ },
{ name: 'keyword', regex: /(if|then|else)/ },
{ name: 'whitespace', regex: /(\s+)/ },
]);
class IntegerNode { constructor(value) { this.value = value; } }
class IfNode { constructor(condition, trueBranch, falseBranch) { this.condition = condition; this.trueBranch = trueBranch; this.falseBranch = falseBranch; } }
const integerRule = rules.then(
rules.tokenOfType('integer'),
(value) => new IntegerNode(parseInt(value, 10))
);
const expressionRule = rules.rule(() =>
rules.firstOf('expression', integerRule, ifRule)
);
const ifRule = rules.sequence(
rules.token('keyword', 'if'),
rules.sequence.cut(),
rules.sequence.capture(expressionRule),
rules.token('keyword', 'then'),
rules.sequence.capture(expressionRule),
rules.token('keyword', 'else'),
rules.sequence.capture(expressionRule)
).map((condition, trueBranch, falseBranch) =>
new IfNode(condition, trueBranch, falseBranch)
);
const parser = new Parser();
const tokens = tokeniser.tokenise('if 1 then 2 else 3');
try {
const result = parser.parseTokens(expressionRule, tokens);
console.log(result);
} catch (e) {
console.error(e.message);
}
Errors
Common errors & fixes
Error: Expected keyword "then" but got integer "42"
Parsing failed inside a rule after a cut, preventing backtracking.
fixCheck that the token sequence matches the rule exactly. The error indicates a specific mismatch after the cut point.
TypeError: lop.Parser is not a constructor
Using import or require incorrectly; likely used default import instead of named.
fixUse const { Parser } = require('lop'); or import { Parser } from 'lop'; Error: First argument to rules.firstOf must be a string (name), followed by rules
Missing rule name as first argument to firstOf.
fixCall rules.firstOf('expressionName', rule1, rule2) with a string name first. Error: The lop module does not have a default export
Attempted import lop from 'lop' which is incorrect.
fixUse import * as lop from 'lop' or import { specific } from 'lop'. Audit
Dependencies
No dependency data recorded yet.