⚠️ This library is still under development. This is a pre-release but some functionalities might still change.
Pegase is a PEG parser generator for JavaScript and TypeScript. It's:
- Inline, meaning grammars are directly expressed as tagged template literals. No generation step, no CLI. Pegase works in symbiosis with JS.
- Fast. Pegase is heavily optimized to be extremely fast while providing an extensive range of features.
- Complete. Pegase has everything you will ever need: an elegant grammar syntax with lots of flexibility, semantic actions, parametrized rules, support for native regexps, error recovery, warnings, integrated AST generation and visitors, cut operator, back references, grammar merging, and a lot more.
- Lightweight. Pegase is a zero-dependency package, and weights around 9kB gzipped.
- Intuitive, in that it lets you express complex processes in very simple ways. You will never feel lost.
- Extensible: You can define your own
Parsersubclasses, add plugins, write custom directives, etc.
The following parses math expressions and calculates the result on the fly:
importpegfrom"pegase";functioncalc(left,op,right){switch(op){case"+": returnleft+right;case"-": returnleft-right;case"*": returnleft*right;case"/": returnleft/right;}}constexpr=peg` expr: term % ("+" | "-") @infix(${calc}) term: fact % ("*" | "/") @infix(${calc}) fact: $integer | '(' expr ')' $integer @number: '-'? [0-9]+`;expr.value("2 + (17-2*30) *(-5)+2")
219expr.test("2* (4 + )/32")
falseexpr.parse("2* (4 + )/32").log()
(1:9) Failure: Expected integer or "("
> 1 | 2* (4 + )/32
| ^
Read more in Building parsers and Semantic action and dataflow.
constbitArray=peg`'[' (0 | 1) % ',' ']'`;bitArray.test(" [ 0,1 ,0 , 1, 1] ");// trueWith, obviously, the possibility to opt-out and do it yourself:
constg=peg` array: '[' _ '1' % ',' _ ']' _: \s+`;g.test("[1,1,1]",{skip: false});// Opt-out as a one-off// Or for all executions by default:g.defaultOptions.skip=false;g.test("[1,1,1]");// falseg.test("[ 1,1,1 ]");// trueg.test("[ 1, 1,1 ]");// falseRead more in Handling whitespaces.
importpeg,{$raw,$warn}from"pegase";functionisCap(str){return/^[A-Z]/.test(str)}constg=peg` classDef: 'class' ($identifier ${()=>{if(!isCap($raw()))$warn("Class names should be capitalized");}}) '{' '}' $identifier: [a-zA-Z]+`;g.parse("class test {").log()
(1:7) Warning: Class names should be capitalized
> 1 | class test {
| ^
(1:13) Failure: Expected "}"
> 1 | class test {
| ^
Read more in Failures and warnings.
With the possibility of omitted parameters and default parameter values.
constg=peg` root: array | array('a') | array('b' | 'c') array(item = \d): '[' commaList(item) ']' commaList(item): item % ','`;g.test("[ a, a, a, a]");// trueg.test("[ a, 5, a, a]");// falseg.test("[b, c]");// trueg.test("[b, a]");// falseg.test("[4, 5, 3, 9, 0]");// trueconstg=peg` bitArray: '[' (bit | sync) % ',' ']' bit: 0 | 1 sync: @@commit ...&(',' | ']')`;g.parse("[0, 4, 1, 2, 0, 1]").log()
(1:5) Failure: Expected "0" or "1"
> 1 | [0, 4, 1, 2, 0, 1]
| ^
(1:11) Failure: Expected "0" or "1"
> 1 | [0, 4, 1, 2, 0, 1]
| ^
Read more in Error recovery.
consttime=/(\d+):(\d+)/;constminutes=peg`${time}${()=>{const[hr,min]=$children();return60*Number(hr)+Number(min);}}`;minutes.value("2:43");// 163Pegase also supports regex literals:
constminutes=peg` /(\d+):(\d+)/ ${()=>{const[hr,min]=$children();return60*Number(hr)+Number(min);}}`;Named capturing groups are converted to Pegase captures:
constdate=/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;constyearIs=peg`${date}${({ year })=>"The year is "+year}`;yearIs.value("2021-08-19");// "The year is 2021"Read more in Working with RegExp.
constprefix=peg` expr: | <>$integer => 'INT' | '+' <a>expr <b>expr => 'PLUS' $integer @raw: \d+`;constsumVisitor={INT: node=>Number(node.$integer),PLUS: node=>$visit(node.a)+$visit(node.b)};prefix.value("182",{visit: sumVisitor});// 182prefix.value("+ 12 + 42 3",{visit: sumVisitor});// 57Read more in AST and visitors.
Here we define a directive @max
importpeg,{$children}from"pegase";peg.plugins.push({directives: {max: parser=>peg`${parser}${()=>Math.max(...$children())}`}});constmax=peg` list: $int+ @max $int: \d+ @number`;max.value("36 12 42 3");// 42Read more in Writing a plugin.
There is so much more to see. To learn more about Pegase, please go to the official website.
