[Pkg-javascript-commits] [node-shell-quote] 93/137: Rewrite parser as a character based scanner

Bastien Roucariès rouca at moszumanska.debian.org
Fri Aug 25 19:19:42 UTC 2017


This is an automated email from the git hooks/post-receive script.

rouca pushed a commit to branch master
in repository node-shell-quote.

commit c7ca9a200350c02fb86c4222b63f15b54a0a0226
Author: Stephen Sugden <me at stephensugden.com>
Date:   Thu Oct 17 17:58:42 2013 -0700

    Rewrite parser as a character based scanner
    
    This may be kind of dumb, but it fixes the quote handling behaviour, and can be
    rewritten as regexes later.
---
 index.js | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 106 insertions(+), 20 deletions(-)

diff --git a/index.js b/index.js
index 604c51a..7ecd705 100644
--- a/index.js
+++ b/index.js
@@ -54,29 +54,115 @@ function parse (s, env) {
     if (!match) return [];
     if (!env) env = {};
     return match.map(function (s) {
-        if (/^'/.test(s)) {
-            return s
-                .replace(/^'|'$/g, '')
-                .replace(/\\(["'\\$`(){}!#&*|])/g, '$1')
-            ;
-        }
-        else if (/^"/.test(s)) {
-            return s.replace(/^"|"$/g, '')
-                .replace(/(^|[^\\])\$(\w+|[*@#?$!0_-])/g, getVar)
-                .replace(/(^|[^\\])\${(\w+|[*@#?$!0_-])}/g, getVar)
-                .replace(/\\([ "'\\$`(){}!#&*|])/g, '$1')
-            ;
-        }
-        else if (RegExp('^' + CONTROL + '$').test(s)) {
+        if (RegExp('^' + CONTROL + '$').test(s)) {
             return { op: s };
         }
-        else return s.replace(
-            /(['"])((\\\1|[^\1])*?)\1|[^'"]+/g,
-            function (s, q) {
-                if (/^['"]/.test(s)) return parse(s, env);
-                return parse('"' + s + '"', env);
+
+        // Hand-written scanner/parser for Bash quoting rules:
+        //
+        //  1. inside single quotes, all characters are printed literally.
+        //  2. inside double quotes, all characters are printed literally
+        //     except variables prefixed by '$' and double quotes prefixed by
+        //     a backslash.
+        //  3. outside of any quotes, backslashes are not printed unless they
+        //     are escaped.
+        //  4. quote context can switch mid-token if there is no whitespace
+        //     between the two quote contexts (e.g. all'one'"token" parses as
+        //     "allonetoken")
+
+        var SQ = "'";
+        var DQ = '"';
+        var BS = '\\';
+        var DS = '$';
+        var quote = false;
+        var varname = false;
+        var esc = false;
+        var out = '';
+        var isGlob = false;
+
+        for (var i = 0, len = s.length; i < len; i++) {
+            var c = s.charAt(i);
+            isGlob = isGlob || (!quote && (c === '*' || c === '?'))
+            if (esc) {
+                out += c;
+                esc = false;
+            }
+            else if (quote) {
+                if (c === quote) {
+                    quote = false;
+                }
+                else if (quote == SQ) {
+                    out += c;
+                }
+                else { // Double quote
+                    if (c === BS) {
+                        i += 1;
+                        c = s.charAt(i);
+                        if (c === DQ || c === BS || c === DS) {
+                            out += c;
+                        } else {
+                            out += BS + c;
+                        }
+                    }
+                    else if (c === DS) {
+                        out += parseEnvVar();
+                    }
+                    else {
+                        out += c
+                    }
+                }
+            }
+            else if (c === DQ || c === SQ) {
+                quote = c
+            }
+            else if (RegExp('^' + CONTROL + '$').test(c)) {
+                return { op: s };
+            }
+            else if (c === BS) {
+                esc = true
+            }
+            else if (c === DS) {
+                out += parseEnvVar();
+            }
+            else out += c;
+        }
+
+        if (isGlob) return {op: 'glob', pattern: out};
+
+        return out
+
+        function parseEnvVar() {
+            i += 1;
+            var varend, varname;
+            //debugger
+            if (s.charAt(i) === '{') {
+                i += 1
+                if (s.charAt(i) === '}') {
+                    throw new Error("Bad substitution: " + s.substr(i - 2, 3));
+                }
+                varend = s.indexOf('}', i);
+                if (varend < 0) {
+                    throw new Error("Bad substitution: " + s.substr(i));
+                }
+                varname = s.substr(i, varend - i);
+                i = varend;
+            }
+            else if (/[*@#?$!_\-]/.test(s.charAt(i))) {
+                varname = s.charAt(i);
+                i += 1;
             }
-        );
+            else {
+                varend = s.substr(i).match(/[^\w\d_]/);
+                if (!varend) {
+                    varname = s.substr(i);
+                    i = s.length;
+                } else {
+                    varname = s.substr(i, varend.index)
+                    i += varend.index - 1;
+                }
+            }
+            return getVar(null, '', varname);
+        }
     });
     
     function getVar (_, pre, key) {

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-shell-quote.git



More information about the Pkg-javascript-commits mailing list