ts-jison icon indicating copy to clipboard operation
ts-jison copied to clipboard

Bison in JavaScript.

ts-jison

This is a fork of Zach Carter [email protected]'s jison module tweaked to use just enough templates to make typescript compilers tollerate the generated parser. This works (I'm using it in a few javascript and typescript projects) and runs all of the original tests except the ones that generated AMD and CommonJS packages. If you want to geek about this, ping ericP on discord or ericprud on gitter.

Updates:

Four previously-independent projects have been placed in this mono-repo:

old npm pakage new npm package monorepo directory
jison @ts-jison/parser-generator packages/parser-generator
jison-lex @ts-jison/lexer-generator packages/lexer-generator
ebnf-parser @ts-jison/ebnf-parser packages/ebnf-parser
lex-parser @ts-jison/lex-parser packages/lex-parser

In addition, the parser and lexer have been factored following DRY principles but mostly to enable coverage tests on parsers (an excellent way to govern test suite coverage of language features). This results in a smaller footprint for projects that include more than on parser.

new npm package monorepo directory
@ts-jison/parser packages/parser
@ts-jison/lexer packages/lexer
@ts-jison/common packages/common
@ts-jison/common-generator packages/common-generator

Example grammar:

This example parses and executes mathematical expressions:

%{
function hexlify (str:string): string { // elide TS types for js-compatibility
  return str.split('').map(ch => '0x' + ch.charCodeAt(0).toString(16)).join(', ')
}
%}

%lex
%no-break-if          (.*[^a-z] | '') 'return' ([^a-z].* | '') // elide trailing 'break;'

%%

\s+                   if (yy.trace) yy.trace(`skipping whitespace ${hexlify(yytext)}`)
[0-9]+("."[0-9]+)?\b  return 'NUMBER'
"-"                   return '-'
"+"                   return '+'
"("                   return '('
")"                   return ')'
<<EOF>>               return 'EOF'
.                     return 'INVALID'

/lex

%left '+' '-'
%left UMINUS
%start expr

%%

expr: e EOF                 { if (yy.trace)
                                yy.trace('returning', $1);
                              return $1; } ; // return e

e   : e '+' e               {$$ = $1+$3;}
    | e '-' e               {$$ = $1-$3;}
    | '-' e %prec UMINUS    {$$ = -$2;}
    | '(' e ')'             {$$ = $2;}
    | NUMBER                {$$ = Number(yytext);} ;

See packages/parser-generator/examples/ for examples and scripts for invocation.

Example compilation:

Convert the .jison file to a TS file:

ts-jison -t typescript -n TsCalc -n TsCalc -o ts-calculator.ts ts-calculator.jison

Convert the .jison file to a JS file:

ts-jison -n TsCalc -n TsCalc -o js-calculator.js js-calculator.jison

Example invocation:

const ParserAndLexer = require('./ts-calculator');

  const txt = ``;
  const res = new ParserAndLexer.TsCalcParser().parse(txt);
  console.log(txt.trim(), '=', res);

or for JS:

const ParserAndLexer = require('./js-calculator');

Docs

See parser-generator docs for more details.

Building from git

git clone ...
cd <cloned repo>
npm ci
for d in packages/{common,lexer,parser}/; do (cd $d && tsc -b tsconfig.package.json); done
lerna bootstrap
npm t

During development, you have to repeat the lerna bootstrap command to get to a steady state because bootstrap tests that the build worked and doesn't seem to reliably build in the order of package dependencies (PRs welcome!).

How to contribute

See CONTRIBUTING.md for contribution guidelines, how to run the tests, etc.

Projects using Jison

View them on the wiki, or add your own.

Contributors

Githubbers

Special thanks to Jarred Ligatti, Manuel E. Bermúdez

Please see the license in this directory.