[hmm long answer, I wish it were shorter...]
Correct, the parser technology is built in JavaScript and runs in a browser and in node.js.
I was getting at something else. It’s my fault that the idea wasn’t made clear. Let’s try again:
1) I generate compilers using Ohm-JS that transpile from syntax I invent to other languages like Common Lisp, Python and JS (I believe that I could do more languages, but I haven’t needed to do so (FYI, I have a P.O.C. WASM generator, but more work is needed (this was my first encounter with WASM and more learning curve is needed))).
2) Then, I run those generated compilers to compile code written in the new languages.
3) Then, I run the generated code on the command line, and, sometimes, in the browser.
Ohm-JS, based on PEG, is the game changer in the way I now look at problems. CFGs (LR(k), YACC, etc.), REGEX, and, hand-written recursive descent parsers are just too cumbersome to use in the same way that I use Ohm-JS.
As an aside, one of the first things I wrote was a compiler that produced code that could be bolted into an Ohm-JS project, with the result that, in many use-cases, I don’t have to write any JavaScript code at all. I can write the grammar in Ohm’s grammar syntax and I can write the transform in my own FABrication syntax, which is more succinct than JS.
Further aside: the first thing I did with Ohm-JS was to write a Scheme-subset-to-JS transpiler and used it to convert Nils Holm’s PROLOG in Scheme to JavaScript.
Example: I am deeply interested in true concurrency. My code uses messages that look like:
⟨a b c d⟩
and I use Ohm-JS to transpile this nano-syntax into something like:
⟨Message a b c d⟩
using 2 specifications:
1. ‛⟪«p» «d» «s» «m»⟫’
2. ‛⟨Message «p» «d» «s» «m»⟩’
N.B. the whole spec for the pattern matching is 1 line long, and, the whole spec for transforming is 1 line long.
This specific example could be done with a Python script (or sed with Unicode support), but there are other details that I’m trying to skip over for this example, e.g. messages might contain other messages recursively, for which it helps to have a parser that can express matching brackets.
The input to Ohm-JS is a JS String. The output of my FABricator compiler is a JS String. All of the above steps can be done in one fell-swoop in a JavaScript program that feeds strings to Ohm-JS and calls Ohm-JS twice. At one point, I need to compile a generated String to executable code. JavaScript’s “eval()” does this. (A “compiler” is “eval()“)
Example: here’s a contrived example of something that I would never do with YACC, but would do with Ohm-JS:
Contrived Problem: scan this big JavaScript program and list every name of every top-level function. Using YACC, you need to write a full spec (“grammar”) for JavaScript, with PEG (Ohm-JS), you can say something more obvious and succint: a function is
function id (...) { ... }
where the ‘...’ stuff is anything including recursively bracketed bits. The point here is not whether I wrote a correct pattern match, but, the difference between “omg, I have to write a grammar for every nook and cranny in JavaScript” vs. writing a grammar with “I don’t care about this part”. This contrived example can probably be done with a REGEX, but if the problem is expanded to be something like “list every function with the name of each parameter” then REGEX works less-well than a parser.