diff --git a/README.md b/README.md index 1e62d8d..bb0f0ea 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ Parsimmon supports IE7 and newer browsers, along with [Node.js][]. It can be use ## Examples -See the [examples][] directory for annotated examples of parsing JSON, Lisp, and math. +See the [examples][] directory for annotated examples of parsing JSON, Lisp, a Python-ish language, and math. ## Basics diff --git a/examples/.eslintrc b/examples/.eslintrc index eb099a6..d061b2b 100644 --- a/examples/.eslintrc +++ b/examples/.eslintrc @@ -1,6 +1,7 @@ { "env": { - "node": true + "node": true, + "es6": true }, "rules": { "no-console": "off" diff --git a/examples/json.js b/examples/json.js index 28130c7..2c45718 100644 --- a/examples/json.js +++ b/examples/json.js @@ -1,11 +1,9 @@ -var fs = require('fs'); -var path = require('path'); var util = require('util'); -var P = require('../src/parsimmon'); +var P = require('..'); /////////////////////////////////////////////////////////////////////// -// Turn escaped characters into real ones (e.g. "\\n" becoems "\n"). +// Turn escaped characters into real ones (e.g. "\\n" becomes "\n"). function interpretEscapes(str) { var escapes = { b: '\b', @@ -96,18 +94,27 @@ var object = /////////////////////////////////////////////////////////////////////// -var source = process.argv[2] || path.resolve(__dirname, '..', 'package.json'); -var result = json.parse(fs.readFileSync(source, 'utf-8')); +var text = `\ +{ + "id": "a thing\\nice\tab", + "another property!" + : "also cool" + , "weird formatting is ok too........😂": 123.45e1, + "": [ + true, false, null, + "", + " ", + {}, + {"": {}} + ] +} +`; function prettyPrint(x) { - console.log(util.inspect(x, {depth: null, colors: 'auto'})); + var opts = {depth: null, colors: 'auto'}; + var s = util.inspect(x, opts); + console.log(s); } -if (result.status) { - prettyPrint(result.value); -} else { - console.log('Parse failure'); - console.log('============='); - console.log(); - prettyPrint(result); -} +var ast = json.tryParse(text); +prettyPrint(ast); diff --git a/examples/lisp.js b/examples/lisp.js index 50fb830..d273f4c 100644 --- a/examples/lisp.js +++ b/examples/lisp.js @@ -1,6 +1,5 @@ -var fs = require('fs'); var util = require('util'); -var P = require('../src/parsimmon'); +var P = require('../'); /////////////////////////////////////////////////////////////////////// @@ -38,18 +37,15 @@ var Lisp = spaced(LExpression); /////////////////////////////////////////////////////////////////////// -var source = process.argv[2]; -var result = Lisp.parse(fs.readFileSync(source, 'utf-8')); +var text = `\ +(list 1 2 (cons 1 (list))) +`; function prettyPrint(x) { - console.log(util.inspect(x, {depth: null, colors: 'auto'})); + var opts = {depth: null, colors: 'auto'}; + var s = util.inspect(x, opts); + console.log(s); } -if (result.status) { - prettyPrint(result.value); -} else { - console.log('Parse failure'); - console.log('============='); - console.log(); - prettyPrint(result); -} +var ast = Lisp.tryParse(text); +prettyPrint(ast); diff --git a/examples/math.js b/examples/math.js index 87ce290..a8f2191 100644 --- a/examples/math.js +++ b/examples/math.js @@ -1,6 +1,5 @@ -var fs = require('fs'); var util = require('util'); -var P = require('../src/parsimmon'); +var P = require('..'); // This parser supports basic math with + - * / ^, unary negation, factorial, // and parentheses. It does not evaluate the math, just turn it into a series of @@ -166,18 +165,15 @@ var MyMath = spaced(tableParser); /////////////////////////////////////////////////////////////////////// -var source = process.argv[2]; -var result = MyMath.parse(fs.readFileSync(source, 'utf-8')); +var text = `\ +2 + 3 * 4 / 1 - 3 ^ (2!) +`; function prettyPrint(x) { - console.log(util.inspect(x, {depth: null, colors: 'auto'})); + var opts = {depth: null, colors: 'auto'}; + var s = util.inspect(x, opts); + console.log(s); } -if (result.status) { - prettyPrint(result.value); -} else { - console.log('Parse failure'); - console.log('============='); - console.log(); - prettyPrint(result); -} +var ast = MyMath.tryParse(text); +prettyPrint(ast); diff --git a/examples/python-ish.js b/examples/python-ish.js new file mode 100644 index 0000000..3a45d9d --- /dev/null +++ b/examples/python-ish.js @@ -0,0 +1,72 @@ +var util = require('util'); +var P = require('..'); + +/////////////////////////////////////////////////////////////////////// + +// If this were actually Python, "Block" wouldn't be a statement on its own, +// but rather "If" and "While" would be statements that used "Block" inside. +var Statement = + P.lazy(function() { + return P.alt(ExpressionStatement, Block); + }); + +// Just a simple `foo()` style function call. +var FunctionCall = + P.regexp(/[a-z]+/).skip(P.string('()')) + .map(function(s) { return ['FunctionCall', s]; }) + .desc('a function call'); + +// To make it a statement we just need a newline afterward. +var ExpressionStatement = + FunctionCall.skip(P.string('\n')); + +// The general idea of this is to assume there's "block:" on its own line, +// then we capture the whitespace used to indent the first statement of the +// block, and require that every other statement has the same exact string of +// indentation in front of it. +var Block = + P.seq( + P.string('block:\n'), + P.regexp(/[ ]+/), + Statement + ).chain(function(args) { + // `.chain` is called after a parser succeeds. It returns the next parser + // to use for parsing. This allows subsequent parsing to be dependent on + // previous text. + var indent = args[1]; + var statement = args[2]; + return P.string(indent).then(Statement).many() + .map(function(statements) { + return [statement].concat(statements); + }); + }) + .map(function(statements) { + return ['Block', statements]; + }); + +/////////////////////////////////////////////////////////////////////// + +var text = `\ +block: + a() + b() + c() + block: + d() + e() + f() + block: + g() + h() + i() + j() +`; + +function prettyPrint(x) { + var opts = {depth: null, colors: 'auto'}; + var s = util.inspect(x, opts); + console.log(s); +} + +var ast = Block.tryParse(text); +prettyPrint(ast);