Skip to content

Commit 9b485cd

Browse files
authored
Merge pull request #110 from vim-jp/new-dict-syntax
Implement #{ ... } syntax
2 parents 01d2dda + e65a482 commit 9b485cd

File tree

5 files changed

+136
-12
lines changed

5 files changed

+136
-12
lines changed

autoload/vimlparser.vim

+42-4
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ let s:TOKEN_DOTDOTDOT = 63
205205
let s:TOKEN_SHARP = 64
206206
let s:TOKEN_ARROW = 65
207207
let s:TOKEN_BLOB = 66
208+
let s:TOKEN_LITCOPEN = 67
208209

209210
let s:MAX_FUNC_ARGS = 20
210211

@@ -2772,8 +2773,13 @@ function! s:ExprTokenizer.get2()
27722773
call r.seek_cur(1)
27732774
return self.token(s:TOKEN_COLON, ':', pos)
27742775
elseif c ==# '#'
2775-
call r.seek_cur(1)
2776-
return self.token(s:TOKEN_SHARP, '#', pos)
2776+
if r.p(1) ==# '{'
2777+
call r.seek_cur(2)
2778+
return self.token(s:TOKEN_LITCOPEN, '#{', pos)
2779+
else
2780+
call r.seek_cur(1)
2781+
return self.token(s:TOKEN_SHARP, '#', pos)
2782+
endif
27772783
elseif c ==# '('
27782784
call r.seek_cur(1)
27792785
return self.token(s:TOKEN_POPEN, '(', pos)
@@ -2893,6 +2899,29 @@ function! s:ExprTokenizer.get_dstring()
28932899
return s
28942900
endfunction
28952901

2902+
function! s:ExprTokenizer.get_dict_literal_key()
2903+
call self.reader.skip_white()
2904+
let r = self.reader
2905+
let c = r.peek()
2906+
if !s:isalnum(c) && c != '_' && c != '-'
2907+
throw s:Err(printf('unexpected token: %s', token.value), token.pos)
2908+
endif
2909+
let s = c
2910+
call self.reader.seek_cur(1)
2911+
while s:TRUE
2912+
let c = self.reader.p(0)
2913+
if c ==# '<EOF>' || c ==# '<EOL>'
2914+
throw s:Err('unexpectd EOL', self.reader.getpos())
2915+
endif
2916+
if !s:isalnum(c) && c != '_' && c != '-'
2917+
break
2918+
endif
2919+
call self.reader.seek_cur(1)
2920+
let s .= c
2921+
endwhile
2922+
return s
2923+
endfunction
2924+
28962925
let s:ExprParser = {}
28972926

28982927
function! s:ExprParser.new(...)
@@ -3381,6 +3410,7 @@ endfunction
33813410
" 'string'
33823411
" [expr1, ...]
33833412
" {expr1: expr1, ...}
3413+
" #{literal_key1: expr1, ...}
33843414
" {args -> expr1}
33853415
" &option
33863416
" (expr1)
@@ -3437,7 +3467,8 @@ function! s:ExprParser.parse_expr9()
34373467
endif
34383468
endwhile
34393469
endif
3440-
elseif token.type == s:TOKEN_COPEN
3470+
elseif token.type == s:TOKEN_COPEN || token.type == s:TOKEN_LITCOPEN
3471+
let is_litdict = token.type == s:TOKEN_LITCOPEN
34413472
let savepos = self.reader.tell()
34423473
let nodepos = token.pos
34433474
let token = self.tokenizer.get()
@@ -3525,7 +3556,7 @@ function! s:ExprParser.parse_expr9()
35253556
return node
35263557
endif
35273558
while 1
3528-
let key = self.parse_expr1()
3559+
let key = is_litdict ? self.parse_dict_literal_key() : self.parse_expr1()
35293560
let token = self.tokenizer.get()
35303561
if token.type == s:TOKEN_CCLOSE
35313562
if !empty(node.value)
@@ -3590,6 +3621,13 @@ function! s:ExprParser.parse_expr9()
35903621
return node
35913622
endfunction
35923623

3624+
function! s:ExprParser.parse_dict_literal_key()
3625+
let node = s:Node(s:NODE_STRING)
3626+
let node.pos = self.reader.tell()
3627+
let node.value = "'" . self.tokenizer.get_dict_literal_key() . "'"
3628+
return node
3629+
endfunction
3630+
35933631
" SUBSCRIPT or CONCAT
35943632
" dict "." [0-9A-Za-z_]+ => (subscript dict key)
35953633
" str "." expr6 => (concat str expr6)

js/vimlparser.js

+43-4
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,7 @@ var TOKEN_DOTDOTDOT = 63;
397397
var TOKEN_SHARP = 64;
398398
var TOKEN_ARROW = 65;
399399
var TOKEN_BLOB = 66;
400+
var TOKEN_LITCOPEN = 67;
400401
var MAX_FUNC_ARGS = 20;
401402
function isalpha(c) {
402403
return viml_eqregh(c, "^[A-Za-z]$");
@@ -2552,8 +2553,14 @@ ExprTokenizer.prototype.get2 = function() {
25522553
return this.token(TOKEN_COLON, ":", pos);
25532554
}
25542555
else if (c == "#") {
2555-
r.seek_cur(1);
2556-
return this.token(TOKEN_SHARP, "#", pos);
2556+
if (r.p(1) == "{") {
2557+
r.seek_cur(2);
2558+
return this.token(TOKEN_LITCOPEN, "#{", pos);
2559+
}
2560+
else {
2561+
r.seek_cur(1);
2562+
return this.token(TOKEN_SHARP, "#", pos);
2563+
}
25572564
}
25582565
else if (c == "(") {
25592566
r.seek_cur(1);
@@ -2697,6 +2704,29 @@ ExprTokenizer.prototype.get_dstring = function() {
26972704
return s;
26982705
}
26992706

2707+
ExprTokenizer.prototype.get_dict_literal_key = function() {
2708+
this.reader.skip_white();
2709+
var r = this.reader;
2710+
var c = r.peek();
2711+
if (!isalnum(c) && c != "_" && c != "-") {
2712+
throw Err(viml_printf("unexpected token: %s", token.value), token.pos);
2713+
}
2714+
var s = c;
2715+
this.reader.seek_cur(1);
2716+
while (TRUE) {
2717+
var c = this.reader.p(0);
2718+
if (c == "<EOF>" || c == "<EOL>") {
2719+
throw Err("unexpectd EOL", this.reader.getpos());
2720+
}
2721+
if (!isalnum(c) && c != "_" && c != "-") {
2722+
break;
2723+
}
2724+
this.reader.seek_cur(1);
2725+
s += c;
2726+
}
2727+
return s;
2728+
}
2729+
27002730
function ExprParser() { this.__init__.apply(this, arguments); }
27012731
ExprParser.prototype.__init__ = function(reader) {
27022732
this.reader = reader;
@@ -3228,6 +3258,7 @@ ExprParser.prototype.parse_expr8 = function() {
32283258
// 'string'
32293259
// [expr1, ...]
32303260
// {expr1: expr1, ...}
3261+
// #{literal_key1: expr1, ...}
32313262
// {args -> expr1}
32323263
// &option
32333264
// (expr1)
@@ -3292,7 +3323,8 @@ ExprParser.prototype.parse_expr9 = function() {
32923323
}
32933324
}
32943325
}
3295-
else if (token.type == TOKEN_COPEN) {
3326+
else if (token.type == TOKEN_COPEN || token.type == TOKEN_LITCOPEN) {
3327+
var is_litdict = token.type == TOKEN_LITCOPEN;
32963328
var savepos = this.reader.tell();
32973329
var nodepos = token.pos;
32983330
var token = this.tokenizer.get();
@@ -3387,7 +3419,7 @@ ExprParser.prototype.parse_expr9 = function() {
33873419
return node;
33883420
}
33893421
while (1) {
3390-
var key = this.parse_expr1();
3422+
var key = is_litdict ? this.parse_dict_literal_key() : this.parse_expr1();
33913423
var token = this.tokenizer.get();
33923424
if (token.type == TOKEN_CCLOSE) {
33933425
if (!viml_empty(node.value)) {
@@ -3463,6 +3495,13 @@ ExprParser.prototype.parse_expr9 = function() {
34633495
return node;
34643496
}
34653497

3498+
ExprParser.prototype.parse_dict_literal_key = function() {
3499+
var node = Node(NODE_STRING);
3500+
node.pos = this.reader.tell();
3501+
node.value = "'" + this.tokenizer.get_dict_literal_key() + "'";
3502+
return node;
3503+
}
3504+
34663505
// SUBSCRIPT or CONCAT
34673506
// dict "." [0-9A-Za-z_]+ => (subscript dict key)
34683507
// str "." expr6 => (concat str expr6)

py/vimlparser.py

+35-4
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,7 @@ def viml_type(obj):
351351
TOKEN_SHARP = 64
352352
TOKEN_ARROW = 65
353353
TOKEN_BLOB = 66
354+
TOKEN_LITCOPEN = 67
354355
MAX_FUNC_ARGS = 20
355356
def isalpha(c):
356357
return viml_eqregh(c, "^[A-Za-z]$")
@@ -2023,8 +2024,12 @@ def get2(self):
20232024
r.seek_cur(1)
20242025
return self.token(TOKEN_COLON, ":", pos)
20252026
elif c == "#":
2026-
r.seek_cur(1)
2027-
return self.token(TOKEN_SHARP, "#", pos)
2027+
if r.p(1) == "{":
2028+
r.seek_cur(2)
2029+
return self.token(TOKEN_LITCOPEN, "#{", pos)
2030+
else:
2031+
r.seek_cur(1)
2032+
return self.token(TOKEN_SHARP, "#", pos)
20282033
elif c == "(":
20292034
r.seek_cur(1)
20302035
return self.token(TOKEN_POPEN, "(", pos)
@@ -2131,6 +2136,24 @@ def get_dstring(self):
21312136
s += c
21322137
return s
21332138

2139+
def get_dict_literal_key(self):
2140+
self.reader.skip_white()
2141+
r = self.reader
2142+
c = r.peek()
2143+
if not isalnum(c) and c != "_" and c != "-":
2144+
raise VimLParserException(Err(viml_printf("unexpected token: %s", token.value), token.pos))
2145+
s = c
2146+
self.reader.seek_cur(1)
2147+
while TRUE:
2148+
c = self.reader.p(0)
2149+
if c == "<EOF>" or c == "<EOL>":
2150+
raise VimLParserException(Err("unexpectd EOL", self.reader.getpos()))
2151+
if not isalnum(c) and c != "_" and c != "-":
2152+
break
2153+
self.reader.seek_cur(1)
2154+
s += c
2155+
return s
2156+
21342157
class ExprParser:
21352158
def __init__(self, reader):
21362159
self.reader = reader
@@ -2575,6 +2598,7 @@ def parse_expr8(self):
25752598
# 'string'
25762599
# [expr1, ...]
25772600
# {expr1: expr1, ...}
2601+
# #{literal_key1: expr1, ...}
25782602
# {args -> expr1}
25792603
# &option
25802604
# (expr1)
@@ -2627,7 +2651,8 @@ def parse_expr9(self):
26272651
break
26282652
else:
26292653
raise VimLParserException(Err(viml_printf("unexpected token: %s", token.value), token.pos))
2630-
elif token.type == TOKEN_COPEN:
2654+
elif token.type == TOKEN_COPEN or token.type == TOKEN_LITCOPEN:
2655+
is_litdict = token.type == TOKEN_LITCOPEN
26312656
savepos = self.reader.tell()
26322657
nodepos = token.pos
26332658
token = self.tokenizer.get()
@@ -2703,7 +2728,7 @@ def parse_expr9(self):
27032728
self.tokenizer.get()
27042729
return node
27052730
while 1:
2706-
key = self.parse_expr1()
2731+
key = self.parse_dict_literal_key() if is_litdict else self.parse_expr1()
27072732
token = self.tokenizer.get()
27082733
if token.type == TOKEN_CCLOSE:
27092734
if not viml_empty(node.value):
@@ -2759,6 +2784,12 @@ def parse_expr9(self):
27592784
raise VimLParserException(Err(viml_printf("unexpected token: %s", token.value), token.pos))
27602785
return node
27612786

2787+
def parse_dict_literal_key(self):
2788+
node = Node(NODE_STRING)
2789+
node.pos = self.reader.tell()
2790+
node.value = "'" + self.tokenizer.get_dict_literal_key() + "'"
2791+
return node
2792+
27622793
# SUBSCRIPT or CONCAT
27632794
# dict "." [0-9A-Za-z_]+ => (subscript dict key)
27642795
# str "." expr6 => (concat str expr6)

test/test_litdict.ok

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
(echo (dict))
2+
(echo (dict ('foo-bar' 42)))
3+
(echo (dict ('foo-' 42)))
4+
(echo (dict ('-bar' 42)))
5+
(echo (dict ('1-1' 0)))
6+
(echo (dict ('one' 1) ('two2' 2) ('3three' 3) ('44' 4)))
7+
(echo (dict ('x' (dict))))
8+
(echo (list (dict)))

test/test_litdict.vim

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
echo #{}
2+
echo #{foo-bar: 42}
3+
echo #{foo-: 42}
4+
echo #{-bar: 42}
5+
echo #{1-1:0}
6+
echo #{one: 1, two2: 2, 3three: 3, 44: 4}
7+
echo #{x : {},}
8+
echo [#{},]

0 commit comments

Comments
 (0)