diff --git a/js/vimlparser.js b/js/vimlparser.js index bd53510e..79a43cb4 100644 --- a/js/vimlparser.js +++ b/js/vimlparser.js @@ -1787,10 +1787,17 @@ VimLParser.prototype.parse_cmd_let = function() { // :let if (this.ends_excmds(this.reader.peek())) { this.reader.seek_set(pos); - this.parse_cmd_common(); + var node = Node(NODE_LET); + node.pos = this.ea.cmdpos; + node.ea = this.ea; + node.left = NIL; + node.list = NIL; + node.rest = NIL; + node.right = NIL; + this.add_node(node); return; } - var lhs = this.parse_letlhs(); + var lhs = this.parse_letlhs(FALSE); this.reader.skip_white(); var s1 = this.reader.peekn(1); var s2 = this.reader.peekn(2); @@ -1800,8 +1807,14 @@ VimLParser.prototype.parse_cmd_let = function() { } // :let {var-name} .. if (this.ends_excmds(s1) || s2 != "+=" && s2 != "-=" && s2 != ".=" && s2 != "..=" && s2 != "*=" && s2 != "/=" && s2 != "%=" && s1 != "=") { - this.reader.seek_set(pos); - this.parse_cmd_common(); + var node = Node(NODE_LET); + node.pos = this.ea.cmdpos; + node.ea = this.ea; + node.left = lhs.left; + node.list = lhs.list; + node.rest = lhs.rest; + node.right = NIL; + this.add_node(node); return; } // :let left op right @@ -1833,17 +1846,29 @@ VimLParser.prototype.parse_cmd_const = function() { this.reader.skip_white(); // :const if (this.ends_excmds(this.reader.peek())) { - this.reader.seek_set(pos); - this.parse_cmd_common(); + var node = Node(NODE_CONST); + node.pos = this.ea.cmdpos; + node.ea = this.ea; + node.left = NIL; + node.list = NIL; + node.rest = NIL; + node.right = NIL; + this.add_node(node); return; } - var lhs = this.parse_constlhs(); + var lhs = this.parse_letlhs(TRUE); this.reader.skip_white(); var s1 = this.reader.peekn(1); // :const {var-name} if (this.ends_excmds(s1) || s1 != "=") { - this.reader.seek_set(pos); - this.parse_cmd_common(); + var node = Node(NODE_CONST); + node.pos = this.ea.cmdpos; + node.ea = this.ea; + node.left = lhs.left; + node.list = lhs.list; + node.rest = lhs.rest; + node.right = NIL; + this.add_node(node); return; } // :const left op right @@ -1983,7 +2008,7 @@ VimLParser.prototype.parse_cmd_for = function() { node.left = NIL; node.right = NIL; node.endfor = NIL; - var lhs = this.parse_letlhs(); + var lhs = this.parse_letlhs(FALSE); node.left = lhs.left; node.list = lhs.list; node.rest = lhs.rest; @@ -2195,7 +2220,6 @@ VimLParser.prototype.parse_lvalue = function() { throw Err("Invalid Expression", node.pos); } -// TODO: merge with s:VimLParser.parse_lvalue() VimLParser.prototype.parse_constlvalue = function() { var p = new LvalueParser(this.reader); var node = p.parse(); @@ -2238,7 +2262,7 @@ VimLParser.prototype.parse_lvaluelist = function() { } // FIXME: -VimLParser.prototype.parse_letlhs = function() { +VimLParser.prototype.parse_letlhs = function(is_const) { var lhs = {"left":NIL, "list":NIL, "rest":NIL}; var tokenizer = new ExprTokenizer(this.reader); if (tokenizer.peek().type == TOKEN_SQOPEN) { @@ -2270,47 +2294,11 @@ VimLParser.prototype.parse_letlhs = function() { } } } - else { - lhs.left = this.parse_lvalue(); - } - return lhs; -} - -// TODO: merge with s:VimLParser.parse_letlhs() ? -VimLParser.prototype.parse_constlhs = function() { - var lhs = {"left":NIL, "list":NIL, "rest":NIL}; - var tokenizer = new ExprTokenizer(this.reader); - if (tokenizer.peek().type == TOKEN_SQOPEN) { - tokenizer.get(); - lhs.list = []; - while (TRUE) { - var node = this.parse_lvalue(); - viml_add(lhs.list, node); - var token = tokenizer.get(); - if (token.type == TOKEN_SQCLOSE) { - break; - } - else if (token.type == TOKEN_COMMA) { - continue; - } - else if (token.type == TOKEN_SEMICOLON) { - var node = this.parse_lvalue(); - lhs.rest = node; - var token = tokenizer.get(); - if (token.type == TOKEN_SQCLOSE) { - break; - } - else { - throw Err(viml_printf("E475 Invalid argument: %s", token.value), token.pos); - } - } - else { - throw Err(viml_printf("E475 Invalid argument: %s", token.value), token.pos); - } - } + else if (is_const) { + lhs.left = this.parse_constlvalue(); } else { - lhs.left = this.parse_constlvalue(); + lhs.left = this.parse_lvalue(); } return lhs; } @@ -4501,24 +4489,20 @@ Compiler.prototype.compile_excall = function(node) { } Compiler.prototype.compile_let = function(node) { - var left = ""; - if (node.left !== NIL) { - var left = this.compile(node.left); - } - else { - var left = viml_join(node.list.map((function(vval) { return this.compile(vval); }).bind(this)), " "); - if (node.rest !== NIL) { - left += " . " + this.compile(node.rest); - } - var left = "(" + left + ")"; - } - var right = this.compile(node.right); - this.out("(let %s %s %s)", node.op, left, right); + this.compile_letconst(node, "let"); } -// TODO: merge with s:Compiler.compile_let() ? Compiler.prototype.compile_const = function(node) { + this.compile_letconst(node, "const"); +} + +Compiler.prototype.compile_letconst = function(node, cmd) { var left = ""; + var right = ""; + if (node.left === NIL && node.right === NIL) { + this.out("(%s)", cmd); + return; + } if (node.left !== NIL) { var left = this.compile(node.left); } @@ -4529,8 +4513,15 @@ Compiler.prototype.compile_const = function(node) { } var left = "(" + left + ")"; } - var right = this.compile(node.right); - this.out("(const %s %s %s)", node.op, left, right); + if (node.right !== NIL) { + var right = this.compile(node.right); + } + if (node.left !== NIL && node.right === NIL) { + this.out("(%s () %s)", cmd, left); + } + else { + this.out("(%s %s %s %s)", cmd, node.op, left, right); + } } Compiler.prototype.compile_unlet = function(node) { diff --git a/py/vimlparser.py b/py/vimlparser.py index 592f1a21..89cfa1b1 100644 --- a/py/vimlparser.py +++ b/py/vimlparser.py @@ -1468,9 +1468,16 @@ def parse_cmd_let(self): # :let if self.ends_excmds(self.reader.peek()): self.reader.seek_set(pos) - self.parse_cmd_common() + node = Node(NODE_LET) + node.pos = self.ea.cmdpos + node.ea = self.ea + node.left = NIL + node.list = NIL + node.rest = NIL + node.right = NIL + self.add_node(node) return - lhs = self.parse_letlhs() + lhs = self.parse_letlhs(FALSE) self.reader.skip_white() s1 = self.reader.peekn(1) s2 = self.reader.peekn(2) @@ -1479,8 +1486,14 @@ def parse_cmd_let(self): s2 = self.reader.peekn(3) # :let {var-name} .. if self.ends_excmds(s1) or s2 != "+=" and s2 != "-=" and s2 != ".=" and s2 != "..=" and s2 != "*=" and s2 != "/=" and s2 != "%=" and s1 != "=": - self.reader.seek_set(pos) - self.parse_cmd_common() + node = Node(NODE_LET) + node.pos = self.ea.cmdpos + node.ea = self.ea + node.left = lhs.left + node.list = lhs.list + node.rest = lhs.rest + node.right = NIL + self.add_node(node) return # :let left op right node = Node(NODE_LET) @@ -1507,16 +1520,28 @@ def parse_cmd_const(self): self.reader.skip_white() # :const if self.ends_excmds(self.reader.peek()): - self.reader.seek_set(pos) - self.parse_cmd_common() + node = Node(NODE_CONST) + node.pos = self.ea.cmdpos + node.ea = self.ea + node.left = NIL + node.list = NIL + node.rest = NIL + node.right = NIL + self.add_node(node) return - lhs = self.parse_constlhs() + lhs = self.parse_letlhs(TRUE) self.reader.skip_white() s1 = self.reader.peekn(1) # :const {var-name} if self.ends_excmds(s1) or s1 != "=": - self.reader.seek_set(pos) - self.parse_cmd_common() + node = Node(NODE_CONST) + node.pos = self.ea.cmdpos + node.ea = self.ea + node.left = lhs.left + node.list = lhs.list + node.rest = lhs.rest + node.right = NIL + self.add_node(node) return # :const left op right node = Node(NODE_CONST) @@ -1636,7 +1661,7 @@ def parse_cmd_for(self): node.left = NIL node.right = NIL node.endfor = NIL - lhs = self.parse_letlhs() + lhs = self.parse_letlhs(FALSE) node.left = lhs.left node.list = lhs.list node.rest = lhs.rest @@ -1808,7 +1833,6 @@ def parse_lvalue(self): return node raise VimLParserException(Err("Invalid Expression", node.pos)) - # TODO: merge with s:VimLParser.parse_lvalue() def parse_constlvalue(self): p = LvalueParser(self.reader) node = p.parse() @@ -1840,7 +1864,7 @@ def parse_lvaluelist(self): return list # FIXME: - def parse_letlhs(self): + def parse_letlhs(self, is_const): lhs = AttributeDict({"left": NIL, "list": NIL, "rest": NIL}) tokenizer = ExprTokenizer(self.reader) if tokenizer.peek().type == TOKEN_SQOPEN: @@ -1864,39 +1888,12 @@ def parse_letlhs(self): raise VimLParserException(Err(viml_printf("E475 Invalid argument: %s", token.value), token.pos)) else: raise VimLParserException(Err(viml_printf("E475 Invalid argument: %s", token.value), token.pos)) + elif is_const: + lhs.left = self.parse_constlvalue() else: lhs.left = self.parse_lvalue() return lhs - # TODO: merge with s:VimLParser.parse_letlhs() ? - def parse_constlhs(self): - lhs = AttributeDict({"left": NIL, "list": NIL, "rest": NIL}) - tokenizer = ExprTokenizer(self.reader) - if tokenizer.peek().type == TOKEN_SQOPEN: - tokenizer.get() - lhs.list = [] - while TRUE: - node = self.parse_lvalue() - viml_add(lhs.list, node) - token = tokenizer.get() - if token.type == TOKEN_SQCLOSE: - break - elif token.type == TOKEN_COMMA: - continue - elif token.type == TOKEN_SEMICOLON: - node = self.parse_lvalue() - lhs.rest = node - token = tokenizer.get() - if token.type == TOKEN_SQCLOSE: - break - else: - raise VimLParserException(Err(viml_printf("E475 Invalid argument: %s", token.value), token.pos)) - else: - raise VimLParserException(Err(viml_printf("E475 Invalid argument: %s", token.value), token.pos)) - else: - lhs.left = self.parse_constlvalue() - return lhs - def ends_excmds(self, c): return c == "" or c == "|" or c == "\"" or c == "" or c == "" @@ -3600,20 +3597,17 @@ def compile_excall(self, node): self.out("(call %s)", self.compile(node.left)) def compile_let(self, node): - left = "" - if node.left is not NIL: - left = self.compile(node.left) - else: - left = viml_join([self.compile(vval) for vval in node.list], " ") - if node.rest is not NIL: - left += " . " + self.compile(node.rest) - left = "(" + left + ")" - right = self.compile(node.right) - self.out("(let %s %s %s)", node.op, left, right) + self.compile_letconst(node, "let") - # TODO: merge with s:Compiler.compile_let() ? def compile_const(self, node): + self.compile_letconst(node, "const") + + def compile_letconst(self, node, cmd): left = "" + right = "" + if node.left is NIL and node.right is NIL: + self.out("(%s)", cmd) + return if node.left is not NIL: left = self.compile(node.left) else: @@ -3621,8 +3615,12 @@ def compile_const(self, node): if node.rest is not NIL: left += " . " + self.compile(node.rest) left = "(" + left + ")" - right = self.compile(node.right) - self.out("(const %s %s %s)", node.op, left, right) + if node.right is not NIL: + right = self.compile(node.right) + if node.left is not NIL and node.right is NIL: + self.out("(%s () %s)", cmd, left) + else: + self.out("(%s %s %s %s)", cmd, node.op, left, right) def compile_unlet(self, node): list = [self.compile(vval) for vval in node.list]