| Leo Repp | 58b9f11 | 2021-11-22 11:57:47 +0100 | [diff] [blame^] | 1 | #!/usr/bin/env node |
| 2 | /* |
| 3 | Copyright JS Foundation and other contributors, https://js.foundation/ |
| 4 | |
| 5 | Redistribution and use in source and binary forms, with or without |
| 6 | modification, are permitted provided that the following conditions are met: |
| 7 | |
| 8 | * Redistributions of source code must retain the above copyright |
| 9 | notice, this list of conditions and the following disclaimer. |
| 10 | * Redistributions in binary form must reproduce the above copyright |
| 11 | notice, this list of conditions and the following disclaimer in the |
| 12 | documentation and/or other materials provided with the distribution. |
| 13 | |
| 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 17 | ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY |
| 18 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| 21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| 23 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 24 | */ |
| 25 | |
| 26 | /*jslint sloppy:true node:true rhino:true */ |
| 27 | |
| 28 | var fs, esprima, fname, forceFile, content, options, syntax; |
| 29 | |
| 30 | if (typeof require === 'function') { |
| 31 | fs = require('fs'); |
| 32 | try { |
| 33 | esprima = require('esprima'); |
| 34 | } catch (e) { |
| 35 | esprima = require('../'); |
| 36 | } |
| 37 | } else if (typeof load === 'function') { |
| 38 | try { |
| 39 | load('esprima.js'); |
| 40 | } catch (e) { |
| 41 | load('../esprima.js'); |
| 42 | } |
| 43 | } |
| 44 | |
| 45 | // Shims to Node.js objects when running under Rhino. |
| 46 | if (typeof console === 'undefined' && typeof process === 'undefined') { |
| 47 | console = { log: print }; |
| 48 | fs = { readFileSync: readFile }; |
| 49 | process = { argv: arguments, exit: quit }; |
| 50 | process.argv.unshift('esparse.js'); |
| 51 | process.argv.unshift('rhino'); |
| 52 | } |
| 53 | |
| 54 | function showUsage() { |
| 55 | console.log('Usage:'); |
| 56 | console.log(' esparse [options] [file.js]'); |
| 57 | console.log(); |
| 58 | console.log('Available options:'); |
| 59 | console.log(); |
| 60 | console.log(' --comment Gather all line and block comments in an array'); |
| 61 | console.log(' --loc Include line-column location info for each syntax node'); |
| 62 | console.log(' --range Include index-based range for each syntax node'); |
| 63 | console.log(' --raw Display the raw value of literals'); |
| 64 | console.log(' --tokens List all tokens in an array'); |
| 65 | console.log(' --tolerant Tolerate errors on a best-effort basis (experimental)'); |
| 66 | console.log(' -v, --version Shows program version'); |
| 67 | console.log(); |
| 68 | process.exit(1); |
| 69 | } |
| 70 | |
| 71 | options = {}; |
| 72 | |
| 73 | process.argv.splice(2).forEach(function (entry) { |
| 74 | |
| 75 | if (forceFile || entry === '-' || entry.slice(0, 1) !== '-') { |
| 76 | if (typeof fname === 'string') { |
| 77 | console.log('Error: more than one input file.'); |
| 78 | process.exit(1); |
| 79 | } else { |
| 80 | fname = entry; |
| 81 | } |
| 82 | } else if (entry === '-h' || entry === '--help') { |
| 83 | showUsage(); |
| 84 | } else if (entry === '-v' || entry === '--version') { |
| 85 | console.log('ECMAScript Parser (using Esprima version', esprima.version, ')'); |
| 86 | console.log(); |
| 87 | process.exit(0); |
| 88 | } else if (entry === '--comment') { |
| 89 | options.comment = true; |
| 90 | } else if (entry === '--loc') { |
| 91 | options.loc = true; |
| 92 | } else if (entry === '--range') { |
| 93 | options.range = true; |
| 94 | } else if (entry === '--raw') { |
| 95 | options.raw = true; |
| 96 | } else if (entry === '--tokens') { |
| 97 | options.tokens = true; |
| 98 | } else if (entry === '--tolerant') { |
| 99 | options.tolerant = true; |
| 100 | } else if (entry === '--') { |
| 101 | forceFile = true; |
| 102 | } else { |
| 103 | console.log('Error: unknown option ' + entry + '.'); |
| 104 | process.exit(1); |
| 105 | } |
| 106 | }); |
| 107 | |
| 108 | // Special handling for regular expression literal since we need to |
| 109 | // convert it to a string literal, otherwise it will be decoded |
| 110 | // as object "{}" and the regular expression would be lost. |
| 111 | function adjustRegexLiteral(key, value) { |
| 112 | if (key === 'value' && value instanceof RegExp) { |
| 113 | value = value.toString(); |
| 114 | } |
| 115 | return value; |
| 116 | } |
| 117 | |
| 118 | function run(content) { |
| 119 | syntax = esprima.parse(content, options); |
| 120 | console.log(JSON.stringify(syntax, adjustRegexLiteral, 4)); |
| 121 | } |
| 122 | |
| 123 | try { |
| 124 | if (fname && (fname !== '-' || forceFile)) { |
| 125 | run(fs.readFileSync(fname, 'utf-8')); |
| 126 | } else { |
| 127 | var content = ''; |
| 128 | process.stdin.resume(); |
| 129 | process.stdin.on('data', function(chunk) { |
| 130 | content += chunk; |
| 131 | }); |
| 132 | process.stdin.on('end', function() { |
| 133 | run(content); |
| 134 | }); |
| 135 | } |
| 136 | } catch (e) { |
| 137 | console.log('Error: ' + e.message); |
| 138 | process.exit(1); |
| 139 | } |