I have an AngularJS web application.
I'd like to use peg.js in my application.
I've just written a peg.js grammar: CriteriaValue.pegjs and generated the parser with the command line:
pegjs CriteriaValue.pegjs
, which generated CriteriaValue.js.
Could someone explain to me how to use the parser ?
var result = parser.parse('my string'); doesn't work.
I've created a plunker: http://plnkr.co/edit/Ae05SeZAjKOQ75B3lvLc?p=preview
Short Answer
module.exports
in the first line toparser
<script>
tags so that CriteriaValue.js comes firstHere's the plunker: http://plnkr.co/edit/kiBp2Na9s4PXpenCzQjx?p=preview
Long Answer
Run your original plunker and check the console logs; you'll notice 2 errors:
ReferenceError: Can't find variable: parser (script.js:3)
ReferenceError: Can't find variable: error (CriteriaValue.js:1)
The first error is due to the fact that no
parser
object is ever created in global scope, by script.js or by CriteriaValue.js.Looking at CriteriaValue.js, you can see it's actually assigning the generated parser object to a non-existent
modules.export
. This is the default behavior of PEG.js, as it assumes you're going to use your parser with node.js. The reason you're seeing the error is that there is nomodule
object, so we can't assign to this non-existent object'sexport
property. Changing the assignment toparser
, which is something we can assign to (because PEG.js doesn't use strict mode), avoids this error and makesparser
available for use in script.js.Finally, the parser needs to be created before script.js can use it; hence the reason for the
<script>
swap.For future creation of CriteriaValue.js, do it like this:
This will generate the file so that the object is assigned to the variable
parser
instead ofmodule.exports
.Where AngularJS Comes In
As @dirkk said in the comments, defining the parser as a global variable is bad practice and certainly not the AngularJS way, which is to implement your parser as a service.
The quickest (but not necessarily best) way to do that is to take your already generated CriteriaValue.js code and wrap a service around it. e.g.:
Another option is to fetch the .pegjs file & generate your parser on the client using
PEG.buildParser()
:This makes updating your grammar easier, as you won't have to rewrite your service every time, but it adds a delay in loading your app. The feasibility of this depends on how complex your grammar is & how often it actually needs to change.
Despite how you build your parser, you don't necessarily need to expose the generated parser object directly to the rest of your Angular app. Instead, you can implement a higher-level API for what your app will actually do with this parser (e.g.
validate(input)
,getAST(input)
, etc...). This way, if you decide in the future to switch to a different parser (e.g. Jison), you'll have much less code to change.