diff --git a/autoload/vimlparser.vim b/autoload/vimlparser.vim index 25db0a4..b691659 100644 --- a/autoload/vimlparser.vim +++ b/autoload/vimlparser.vim @@ -143,6 +143,8 @@ let s:NODE_EVAL = 95 let s:NODE_HEREDOC = 96 let s:NODE_METHOD = 97 let s:NODE_ECHOCONSOLE = 98 +let s:NODE_LSHIFT = 99 +let s:NODE_RSHIFT = 100 let s:TOKEN_EOF = 1 let s:TOKEN_EOL = 2 @@ -213,6 +215,8 @@ let s:TOKEN_BLOB = 66 let s:TOKEN_LITCOPEN = 67 let s:TOKEN_DOTDOT = 68 let s:TOKEN_HEREDOC = 69 +let s:TOKEN_LSHIFT = 70 +let s:TOKEN_RSHIFT = 71 let s:MAX_FUNC_ARGS = 20 @@ -3525,6 +3529,9 @@ function! s:ExprTokenizer.get2() abort elseif r.p(1) ==# '#' call r.seek_cur(2) return self.token(s:TOKEN_GTCS, '>#', pos) + elseif r.p(1) ==# '>' + call r.seek_cur(2) + return self.token(s:TOKEN_RSHIFT, '>>', pos) else call r.seek_cur(1) return self.token(s:TOKEN_GT, '>', pos) @@ -3536,6 +3543,9 @@ function! s:ExprTokenizer.get2() abort elseif r.p(1) ==# '#' call r.seek_cur(2) return self.token(s:TOKEN_LTCS, '<#', pos) + elseif r.p(1) ==# '<' + call r.seek_cur(2) + return self.token(s:TOKEN_LSHIFT, '<<', pos) else call r.seek_cur(1) return self.token(s:TOKEN_LT, '<', pos) @@ -4021,7 +4031,7 @@ endfunction " expr6 . expr6 .. " expr6 .. expr6 .. function! s:ExprParser.parse_expr5() abort - let left = self.parse_expr6() + let left = self.parse_expr5_5() while s:TRUE let pos = self.reader.tell() let token = self.tokenizer.get() @@ -4029,24 +4039,51 @@ function! s:ExprParser.parse_expr5() abort let node = s:Node(s:NODE_ADD) let node.pos = token.pos let node.left = left - let node.right = self.parse_expr6() + let node.right = self.parse_expr5_5() let left = node elseif token.type ==# s:TOKEN_MINUS let node = s:Node(s:NODE_SUBTRACT) let node.pos = token.pos let node.left = left - let node.right = self.parse_expr6() + let node.right = self.parse_expr5_5() let left = node elseif token.type ==# s:TOKEN_DOTDOT " TODO check scriptversion? let node = s:Node(s:NODE_CONCAT) let node.pos = token.pos let node.left = left - let node.right = self.parse_expr6() + let node.right = self.parse_expr5_5() let left = node elseif token.type ==# s:TOKEN_DOT " TODO check scriptversion? let node = s:Node(s:NODE_CONCAT) let node.pos = token.pos let node.left = left + let node.right = self.parse_expr5_5() + let left = node + else + call self.reader.seek_set(pos) + break + endif + endwhile + return left +endfunction + +" expr5_5: expr6 << expr6 .. +" expr6 >> expr6 .. +function! s:ExprParser.parse_expr5_5() abort + let left = self.parse_expr6() + while s:TRUE + let pos = self.reader.tell() + let token = self.tokenizer.get() + if token.type ==# s:TOKEN_LSHIFT + let node = s:Node(s:NODE_LSHIFT) + let node.pos = token.pos + let node.left = left + let node.right = self.parse_expr6() + let left = node + elseif token.type ==# s:TOKEN_RSHIFT + let node = s:Node(s:NODE_RSHIFT) + let node.pos = token.pos + let node.left = left let node.right = self.parse_expr6() let left = node else @@ -5151,6 +5188,10 @@ function! s:Compiler.compile(node) abort return self.compile_divide(a:node) elseif a:node.type ==# s:NODE_REMAINDER return self.compile_remainder(a:node) + elseif a:node.type ==# s:NODE_LSHIFT + return self.compile_lshift(a:node) + elseif a:node.type ==# s:NODE_RSHIFT + return self.compile_rshift(a:node) elseif a:node.type ==# s:NODE_NOT return self.compile_not(a:node) elseif a:node.type ==# s:NODE_PLUS @@ -5600,6 +5641,14 @@ function! s:Compiler.compile_remainder(node) abort return printf('(%% %s %s)', self.compile(a:node.left), self.compile(a:node.right)) endfunction +function! s:Compiler.compile_lshift(node) abort + return printf('(<< %s %s)', self.compile(a:node.left), self.compile(a:node.right)) +endfunction + +function! s:Compiler.compile_rshift(node) abort + return printf('(>> %s %s)', self.compile(a:node.left), self.compile(a:node.right)) +endfunction + function! s:Compiler.compile_not(node) abort return printf('(! %s)', self.compile(a:node.left)) endfunction diff --git a/js/vimlparser.js b/js/vimlparser.js index 91fc9c0..47e4c87 100644 --- a/js/vimlparser.js +++ b/js/vimlparser.js @@ -324,6 +324,8 @@ var NODE_EVAL = 95; var NODE_HEREDOC = 96; var NODE_METHOD = 97; var NODE_ECHOCONSOLE = 98; +var NODE_LSHIFT = 99; +var NODE_RSHIFT = 100; var TOKEN_EOF = 1; var TOKEN_EOL = 2; var TOKEN_SPACE = 3; @@ -393,6 +395,8 @@ var TOKEN_BLOB = 66; var TOKEN_LITCOPEN = 67; var TOKEN_DOTDOT = 68; var TOKEN_HEREDOC = 69; +var TOKEN_LSHIFT = 70; +var TOKEN_RSHIFT = 71; var MAX_FUNC_ARGS = 20; function isalpha(c) { return viml_eqregh(c, "^[A-Za-z]$"); @@ -2709,6 +2713,10 @@ ExprTokenizer.prototype.get2 = function() { r.seek_cur(2); return this.token(TOKEN_GTCS, ">#", pos); } + else if (r.p(1) == ">") { + r.seek_cur(2); + return this.token(TOKEN_RSHIFT, ">>", pos); + } else { r.seek_cur(1); return this.token(TOKEN_GT, ">", pos); @@ -2723,6 +2731,10 @@ ExprTokenizer.prototype.get2 = function() { r.seek_cur(2); return this.token(TOKEN_LTCS, "<#", pos); } + else if (r.p(1) == "<") { + r.seek_cur(2); + return this.token(TOKEN_LSHIFT, "<<", pos); + } else { r.seek_cur(1); return this.token(TOKEN_LT, "<", pos); @@ -3274,7 +3286,7 @@ ExprParser.prototype.parse_expr4 = function() { // expr6 . expr6 .. // expr6 .. expr6 .. ExprParser.prototype.parse_expr5 = function() { - var left = this.parse_expr6(); + var left = this.parse_expr5_5(); while (TRUE) { var pos = this.reader.tell(); var token = this.tokenizer.get(); @@ -3282,14 +3294,14 @@ ExprParser.prototype.parse_expr5 = function() { var node = Node(NODE_ADD); node.pos = token.pos; node.left = left; - node.right = this.parse_expr6(); + node.right = this.parse_expr5_5(); var left = node; } else if (token.type == TOKEN_MINUS) { var node = Node(NODE_SUBTRACT); node.pos = token.pos; node.left = left; - node.right = this.parse_expr6(); + node.right = this.parse_expr5_5(); var left = node; } else if (token.type == TOKEN_DOTDOT) { @@ -3297,7 +3309,7 @@ ExprParser.prototype.parse_expr5 = function() { var node = Node(NODE_CONCAT); node.pos = token.pos; node.left = left; - node.right = this.parse_expr6(); + node.right = this.parse_expr5_5(); var left = node; } else if (token.type == TOKEN_DOT) { @@ -3305,6 +3317,35 @@ ExprParser.prototype.parse_expr5 = function() { var node = Node(NODE_CONCAT); node.pos = token.pos; node.left = left; + node.right = this.parse_expr5_5(); + var left = node; + } + else { + this.reader.seek_set(pos); + break; + } + } + return left; +} + +// expr5_5: expr6 << expr6 .. +// expr6 >> expr6 .. +ExprParser.prototype.parse_expr5_5 = function() { + var left = this.parse_expr6(); + while (TRUE) { + var pos = this.reader.tell(); + var token = this.tokenizer.get(); + if (token.type == TOKEN_LSHIFT) { + var node = Node(NODE_LSHIFT); + node.pos = token.pos; + node.left = left; + node.right = this.parse_expr6(); + var left = node; + } + else if (token.type == TOKEN_RSHIFT) { + var node = Node(NODE_RSHIFT); + node.pos = token.pos; + node.left = left; node.right = this.parse_expr6(); var left = node; } @@ -4536,6 +4577,12 @@ Compiler.prototype.compile = function(node) { else if (node.type == NODE_REMAINDER) { return this.compile_remainder(node); } + else if (node.type == NODE_LSHIFT) { + return this.compile_lshift(node); + } + else if (node.type == NODE_RSHIFT) { + return this.compile_rshift(node); + } else if (node.type == NODE_NOT) { return this.compile_not(node); } @@ -5023,6 +5070,14 @@ Compiler.prototype.compile_remainder = function(node) { return viml_printf("(%% %s %s)", this.compile(node.left), this.compile(node.right)); } +Compiler.prototype.compile_lshift = function(node) { + return viml_printf("(<< %s %s)", this.compile(node.left), this.compile(node.right)); +} + +Compiler.prototype.compile_rshift = function(node) { + return viml_printf("(>> %s %s)", this.compile(node.left), this.compile(node.right)); +} + Compiler.prototype.compile_not = function(node) { return viml_printf("(! %s)", this.compile(node.left)); } diff --git a/py/vimlparser.py b/py/vimlparser.py index f0562b6..3a1c1ad 100644 --- a/py/vimlparser.py +++ b/py/vimlparser.py @@ -311,6 +311,8 @@ def viml_stridx(a, b): NODE_HEREDOC = 96 NODE_METHOD = 97 NODE_ECHOCONSOLE = 98 +NODE_LSHIFT = 99 +NODE_RSHIFT = 100 TOKEN_EOF = 1 TOKEN_EOL = 2 TOKEN_SPACE = 3 @@ -380,6 +382,8 @@ def viml_stridx(a, b): TOKEN_LITCOPEN = 67 TOKEN_DOTDOT = 68 TOKEN_HEREDOC = 69 +TOKEN_LSHIFT = 70 +TOKEN_RSHIFT = 71 MAX_FUNC_ARGS = 20 @@ -2209,6 +2213,9 @@ def get2(self): elif r.p(1) == "#": r.seek_cur(2) return self.token(TOKEN_GTCS, ">#", pos) + elif r.p(1) == ">": + r.seek_cur(2) + return self.token(TOKEN_RSHIFT, ">>", pos) else: r.seek_cur(1) return self.token(TOKEN_GT, ">", pos) @@ -2219,6 +2226,9 @@ def get2(self): elif r.p(1) == "#": r.seek_cur(2) return self.token(TOKEN_LTCS, "<#", pos) + elif r.p(1) == "<": + r.seek_cur(2) + return self.token(TOKEN_LSHIFT, "<<", pos) else: r.seek_cur(1) return self.token(TOKEN_LT, "<", pos) @@ -2666,7 +2676,7 @@ def parse_expr4(self): # expr6 . expr6 .. # expr6 .. expr6 .. def parse_expr5(self): - left = self.parse_expr6() + left = self.parse_expr5_5() while TRUE: pos = self.reader.tell() token = self.tokenizer.get() @@ -2674,26 +2684,50 @@ def parse_expr5(self): node = Node(NODE_ADD) node.pos = token.pos node.left = left - node.right = self.parse_expr6() + node.right = self.parse_expr5_5() left = node elif token.type == TOKEN_MINUS: node = Node(NODE_SUBTRACT) node.pos = token.pos node.left = left - node.right = self.parse_expr6() + node.right = self.parse_expr5_5() left = node elif token.type == TOKEN_DOTDOT: # TODO check scriptversion? node = Node(NODE_CONCAT) node.pos = token.pos node.left = left - node.right = self.parse_expr6() + node.right = self.parse_expr5_5() left = node elif token.type == TOKEN_DOT: # TODO check scriptversion? node = Node(NODE_CONCAT) node.pos = token.pos node.left = left + node.right = self.parse_expr5_5() + left = node + else: + self.reader.seek_set(pos) + break + return left + + # expr5_5: expr6 << expr6 .. + # expr6 >> expr6 .. + def parse_expr5_5(self): + left = self.parse_expr6() + while TRUE: + pos = self.reader.tell() + token = self.tokenizer.get() + if token.type == TOKEN_LSHIFT: + node = Node(NODE_LSHIFT) + node.pos = token.pos + node.left = left + node.right = self.parse_expr6() + left = node + elif token.type == TOKEN_RSHIFT: + node = Node(NODE_RSHIFT) + node.pos = token.pos + node.left = left node.right = self.parse_expr6() left = node else: @@ -3647,6 +3681,10 @@ def compile(self, node): return self.compile_divide(node) elif node.type == NODE_REMAINDER: return self.compile_remainder(node) + elif node.type == NODE_LSHIFT: + return self.compile_lshift(node) + elif node.type == NODE_RSHIFT: + return self.compile_rshift(node) elif node.type == NODE_NOT: return self.compile_not(node) elif node.type == NODE_PLUS: @@ -4007,6 +4045,12 @@ def compile_divide(self, node): def compile_remainder(self, node): return viml_printf("(%% %s %s)", self.compile(node.left), self.compile(node.right)) + def compile_lshift(self, node): + return viml_printf("(<< %s %s)", self.compile(node.left), self.compile(node.right)) + + def compile_rshift(self, node): + return viml_printf("(>> %s %s)", self.compile(node.left), self.compile(node.right)) + def compile_not(self, node): return viml_printf("(! %s)", self.compile(node.left)) diff --git a/test/run_command.sh b/test/run_command.sh index 2a079d8..ed43612 100755 --- a/test/run_command.sh +++ b/test/run_command.sh @@ -26,7 +26,7 @@ test_file() { rm -f ${outfile} - ${vimlparser} ${neovim} ${vimfile} &> ${outfile} + ${vimlparser} ${neovim} ${vimfile} 2>&1 | grep -v "^Coverage.py warning" > ${outfile} diffout=$(diff -u ${outfile} ${okfile}) if [ -n "$diffout" ]; then diff --git a/test/test_bitshift.ok b/test/test_bitshift.ok new file mode 100644 index 0000000..ae9ad00 --- /dev/null +++ b/test/test_bitshift.ok @@ -0,0 +1,6 @@ +; Test bitshift operators +(let = a (<< 1 2)) +(let = b (>> 8 2)) +(let = c (+ (<< 2 3) (>> 16 2))) +(let = d (<< (<< 1 2) 3)) +(let = e (>> (>> 32 1) 2)) diff --git a/test/test_bitshift.vim b/test/test_bitshift.vim new file mode 100644 index 0000000..1ef4660 --- /dev/null +++ b/test/test_bitshift.vim @@ -0,0 +1,6 @@ +" Test bitshift operators +let a = 1 << 2 +let b = 8 >> 2 +let c = (2 << 3) + (16 >> 2) +let d = 1 << 2 << 3 +let e = 32 >> 1 >> 2