Skip to main content

Ohm v17.0

v17.0.0 is primarily a cleanup release in preparation for some new features that will be coming soon in minor releases. It contains a few breaking changes (as described below), but they are unlikely to affect the majority of Ohm users.

This version also has experimental support for indentation-sensitive grammars.

Upgrading

any now consumes a full code point

In JavaScript, a string is a sequence of 16-bit code units. Some Unicode characters, such as emoji, are encoded as pairs of 16-bit values. For example, the string '😆' has length 2, but contains a single Unicode code point. Previously, any matched a single 16-bit code unit — even if that unit was part of a surrogate pair. In v17, any now matches a full Unicode character.

Old behaviour:

const g = ohm.grammar('OneChar { start = any }');
g.match('😆').succeeded(); // false

New behaviour (Ohm v17+):

const g = ohm.grammar('OneChar { start = any }');
g.match('😆').succeeded(); // true

Namespace helpers removed

The top-level namespace and extendNamespace functions have been removed. They were never required — it was always possible to use a plain old object in any API that asked for a namespace.

For example, take the following code (which no longer works in v17+):

const ns = ohm.createNamespace();
ns.G = ohm.grammar('G {}');
ns.G2 = ohm.grammar('G2 <: G {}', ns);

In Ohm v17 and in previous versions, the code could instead be written like this:

const ns = {}; // <- Use a normal object literal
ns.G = ohm.grammar('G {}');
ns.G2 = ohm.grammar('G2 <: G {}', ns);

Named exports only

When used as ES module, the ohm-js and ohm-js/extras modules now have only named exports, and no default export. This fixes some issues with the use of Ohm bundles (.ohm-bundle files) when used with JS module bundlers like Webpack and Rollup (e.g., [#377][issue-377]).

As a result, the following code will no longer work (unless your bundler supports synthetic default imports):

import ohm from 'ohm-js';

In Ohm v17, it should be written like this:

import * as ohm from 'ohm-js';

See #386 for more context on this change.

util removed

The util object has been removed from Ohm's public API. The two methods that were relevant to grammar authors — getLineAndColumn and getLineAndColumnMessage — have been moved into the extras module.

Old code (no longer works):

ohm.util.getLineAndColumnMessage(str, [startIdx, endIdx]);

New code (works in Ohm v17+):

import {getLineAndColumnMessage} from 'ohm-js/extras';
// ...
getLineAndColumnMessage(str, [startIdx, endIdx]);

By the way, the Interval class also has a getLineAndColumnMessage method, which can be useful inside of semantic actions. For example, if you are using this method with the sourceString attribute, like this:

getLineAndColumnMessage(aNode.sourceString, [startIdx, endIdx]);

...you can write it this way instead:

aNode.source.getLineAndColumnMessage();

toAST on built-in list rules

Ohm v17 changed the default behavior of toAST for the built-in list rules (ListOf and friends). Both the syntactic (ListOf, ...) and lexical versions (listOf, ...) are now represented as arrays, with the separators discarded. Previously, the syntactic versions were represented by arrays, but with separators included, and the lexical versions were represented as strings (just like other lexical rules).

See #394 for the reasoning behind this change.

New features

Other changes

  • The deprecated grammarFromScriptElement and grammarsFromScriptElements functions have been entirely removed.
  • The primitiveValue property of nodes, which was deprecated in Ohm v16, has now been completely removed — use Node.sourceString instead.