Skip to content

Commit

Permalink
Merge pull request #3930 from masatake/vim--vim9
Browse files Browse the repository at this point in the history
Vim:  support vim9script
  • Loading branch information
masatake committed Feb 4, 2024
2 parents d59d97e + 0ca7759 commit 6c5cba0
Show file tree
Hide file tree
Showing 13 changed files with 177 additions and 40 deletions.
2 changes: 2 additions & 0 deletions Units/parser-vim.r/vim-const.d/args.ctags
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
--sort=no
--fields=+t
4 changes: 4 additions & 0 deletions Units/parser-vim.r/vim-const.d/expected.tags
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
s:CONSTANT input.vim /^const s:CONSTANT = 42$/;" C
matches input-0.vim /^final matches = []$/;" C
names input-0.vim /^const names = ['Betty', 'Peter']$/;" C
LINK input-0.vim /^const LINK: string = '->'$/;" C typeref:typename:string
mylist input-0.vim /^final mylist: list<string> = ['foo']$/;" C typeref:typename:list<string>
10 changes: 10 additions & 0 deletions Units/parser-vim.r/vim-const.d/input-0.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
vim9script

# Taken from https://vim-jp.org/vimdoc-ja/vim9.html#vim9-differences
final matches = []
const names = ['Betty', 'Peter']

const LINK: string = '->'

# Taken from ~/var/vim/runtime/doc/vim9.txt
final mylist: list<string> = ['foo']
2 changes: 2 additions & 0 deletions Units/parser-vim.r/vim9-def-function.d/args.ctags
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
--sort=no
--fields=+tS
3 changes: 2 additions & 1 deletion Units/parser-vim.r/vim9-def-function.d/expected.tags
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
Func input.vim /^def Func()$/;" f
Func input.vim /^def Func()$/;" f signature:()
Func2 input.vim /^def Func2(): number$/;" f typeref:typename:number signature:()
5 changes: 5 additions & 0 deletions Units/parser-vim.r/vim9-def-function.d/input.vim
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
def Func()
enddef

vim9script
def Func2(): number
return 0
enddef
1 change: 1 addition & 0 deletions Units/parser-vim.r/vim9-export.d/args.ctags
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--sort=no
5 changes: 5 additions & 0 deletions Units/parser-vim.r/vim9-export.d/expected.tags
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
EXPORTED_CONST input.vim /^export const EXPORTED_CONST = 1234$/;" C
v input.vim /^export var v = 1$/;" v
f input.vim /^export final f = 2$/;" C
c input.vim /^export const c = 3$/;" C
MyFunc input.vim /^export def MyFunc()$/;" f
12 changes: 12 additions & 0 deletions Units/parser-vim.r/vim9-export.d/input.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
vim9script

export const EXPORTED_CONST = 1234
export var v = 1
export final f = 2
export const c = 3
export def MyFunc()
echo "hello"
enddef

# export class MyClass ...
# export interface MyClass ...
2 changes: 2 additions & 0 deletions Units/parser-vim.r/vim9-var.d/args.ctags
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
--sort=no
--fields=+St
5 changes: 5 additions & 0 deletions Units/parser-vim.r/vim9-var.d/expected.tags
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
cur_menu_name input.vim /^var cur_menu_name = ""$/;" v
cur_menu_nr input.vim /^var cur_menu_nr = 0$/;" v
cur_menu_item input.vim /^var cur_menu_item: number = 0$/;" v typeref:typename:number
cur_menu_char input.vim /^var cur_menu_char = ""$/;" v
language_section input.vim /^var language_section: list<string> =<< trim END$/;" v typeref:typename:list<string>
17 changes: 17 additions & 0 deletions Units/parser-vim.r/vim9-var.d/input.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
vim9script

# Taken from vim/runtime/makemenu.vim

var cur_menu_name = ""
var cur_menu_nr = 0
var cur_menu_item: number = 0
var cur_menu_char = ""

# Taken from vim/runtime/import/dist/vimhighlight.vim

var language_section: list<string> =<< trim END

Highlighting groups for language syntaxes
-----------------------------------------

END
149 changes: 110 additions & 39 deletions parsers/vim.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,25 +81,16 @@ static kindDefinition VimKinds [] = {
* DATA DECLARATIONS
*/

#if 0
typedef enum eException {
ExceptionNone, ExceptionEOF
} exception_t;
#endif

/*
* DATA DEFINITIONS
*/

#if 0
static jmp_buf Exception;
#endif
static bool vim9script;

/*
* FUNCTION DEFINITIONS
*/

static bool parseVimLine (const unsigned char *line, int infunction);
static bool parseVimLine (const unsigned char *line, int parent);

/* This function takes a char pointer, tries to find a scope separator in the
* string, and if it does, returns a pointer to the character after the colon,
Expand Down Expand Up @@ -227,7 +218,7 @@ static const unsigned char *readVimLine (void)
while (isspace (*line))
++line;

if ((int) *line == '"')
if ((int) *line == (vim9script? '#': '"'))
continue; /* skip comment */

break;
Expand All @@ -248,9 +239,42 @@ static const unsigned char *readVimballLine (void)
return line;
}

static vString *parseSignature (const unsigned char *cp,
tagEntryInfo *e,
vString *buf)
static const unsigned char *parseRettype (const unsigned char *cp, tagEntryInfo *e)
{
while (*cp && isspace (*cp))
++cp;

if (!*cp)
return cp;

vString *buf = vStringNew ();
while (*cp && *cp != '#' && *cp != '=')
{
if (isspace (*cp)
&& !vStringIsEmpty(buf)
&& isspace (vStringLast(buf)))
{
++cp;
continue;
}
vStringPut (buf, *cp);
++cp;
}

if (vStringIsEmpty(buf))
return cp;

vStringStripTrailing (buf);
e->extensionFields.typeRef[0] = eStrdup ("typename");
e->extensionFields.typeRef[1] = vStringDeleteUnwrap (buf);

return cp;
}

static vString *parseSignatureAndRettype (const unsigned char *cp,
tagEntryInfo *e,
vString *buf,
bool extractRettype)
{
/* TODO capture parameters */

Expand Down Expand Up @@ -282,12 +306,21 @@ static vString *parseSignature (const unsigned char *cp,
{
e->extensionFields.signature = vStringDeleteUnwrap (buf);
buf = NULL;

if (extractRettype)
{
++cp;
while (*cp && isspace (*cp))
++cp;
if (*cp == ':')
parseRettype (++cp, e);
}
}

return buf;
}

static void parseFunction (const unsigned char *line)
static void parseFunction (const unsigned char *line, int parent, bool definedWithDEF)
{
vString *name = vStringNew ();
vString *signature = NULL;
Expand Down Expand Up @@ -327,12 +360,17 @@ static void parseFunction (const unsigned char *line)
vStringClear (name);

e = getEntryInCorkQueue (index);
if (e && isFieldEnabled (FIELD_SIGNATURE))
if (e)
{
while (*cp && isspace (*cp))
++cp;
if (*cp == '(')
signature = parseSignature (cp, e, NULL);
e->extensionFields.scopeIndex = parent;
if (isFieldEnabled (FIELD_SIGNATURE))
{
while (*cp && isspace (*cp))
++cp;
if (*cp == '(')
signature = parseSignatureAndRettype (cp, e, NULL,
definedWithDEF);
}
}
}
}
Expand All @@ -349,7 +387,8 @@ static void parseFunction (const unsigned char *line)
/* A backslash at the start of a line stands for a line continuation.
* https://vimhelp.org/repeat.txt.html#line-continuation */
if (*cp == '\\')
signature = parseSignature (++cp, e, signature);
signature = parseSignatureAndRettype (++cp, e, signature,
definedWithDEF);
}

if (wordMatchLen (line, "endfunction", 4) || wordMatchLen (line, "enddef", 6))
Expand All @@ -359,7 +398,7 @@ static void parseFunction (const unsigned char *line)
break;
}

parseVimLine (line, true);
parseVimLine (line, index);
}
if (signature)
vStringDelete (signature);
Expand Down Expand Up @@ -519,7 +558,7 @@ static bool parseCommand (const unsigned char *line)
}

/* =<< trim {endmarker} */
static int parserHeredocMarker(const unsigned char *cp)
static int parseHeredocMarker(const unsigned char *cp)
{
while (*cp && isspace (*cp))
++cp;
Expand Down Expand Up @@ -562,7 +601,7 @@ static int parserHeredocMarker(const unsigned char *cp)
* If we have a heredoc end marker at the end of LINE,
* parseVariableOrConstant returns the tag cork index for the marker.
*/
static int parseVariableOrConstant (const unsigned char *line, int infunction, int kindIndex)
static int parseVariableOrConstant (const unsigned char *line, int parent, int kindIndex)
{
vString *name = vStringNew ();
int heredoc = CORK_NIL;
Expand Down Expand Up @@ -594,7 +633,7 @@ static int parseVariableOrConstant (const unsigned char *line, int infunction, i
goto cleanUp;

/* Skip non-global vars in functions */
if (infunction && (*np != ':' || *cp != 'g'))
if (parent != CORK_NIL && (*np != ':' || *cp != 'g'))
goto cleanUp;

/* deal with spaces, $, @ and & */
Expand All @@ -613,10 +652,27 @@ static int parseVariableOrConstant (const unsigned char *line, int infunction, i
vStringPut (name, *cp);
++cp;
} while (isalnum (*cp) || *cp == '_' || *cp == '#' || *cp == ':' || *cp == '$');
makeSimpleTag (name, kindIndex);
vStringClear (name);

heredoc = parserHeredocMarker(cp);
bool hasType = false;
if (*cp && vim9script && !vStringIsEmpty (name) && (vStringLast (name) == ':'))
{
Assert(line != cp);
Assert(*(cp - 1) == ':');
vStringChop (name);
hasType = true;
}

if (!vStringIsEmpty (name))
{
int r = makeSimpleTag (name, kindIndex);
vStringClear (name);

tagEntryInfo *e;
if (hasType && (e = getEntryInCorkQueue (r)))
cp = parseRettype (cp, e);

heredoc = parseHeredocMarker(cp);
}
}

cleanUp:
Expand Down Expand Up @@ -704,12 +760,25 @@ static bool parseMap (const unsigned char *line)
return true;
}

static bool parseVimLine (const unsigned char *line, int infunction)
static bool parseVimLine (const unsigned char *line, int parent)
{
bool readNextLine = true;
int heredoc = CORK_NIL;

if (wordMatchLen (line, "command", 3))
if (vim9script && wordMatchLen (line, "export", 6))
{
line += 6;
while (*line && isspace (*line))
++line;
/* TODO: export should be stored to a field. */
}

if (wordMatchLen (line, "vim9script", 10))
{
vim9script = true;
}

else if (wordMatchLen (line, "command", 3))
{
readNextLine = parseCommand (line);
/* TODO - Handle parseCommand returning false */
Expand All @@ -722,21 +791,21 @@ static bool parseVimLine (const unsigned char *line, int infunction)

else if (wordMatchLen (line, "function", 2) || wordMatchLen (line, "def", 3))
{
parseFunction (skipWord (line));
parseFunction (skipWord (line), parent, vim9script && line[0] == 'd');
}

else if (wordMatchLen (line, "augroup", 3))
{
parseAutogroup (skipWord (line));
}

else if (wordMatchLen (line, "let", 3))
else if (wordMatchLen (line, "let", 3) || (vim9script && wordMatchLen (line, "var", 3)))
{
heredoc = parseVariableOrConstant (skipWord (line), infunction, K_VARIABLE);
heredoc = parseVariableOrConstant (skipWord (line), parent, K_VARIABLE);
}
else if (wordMatchLen (line, "const", 4))
else if (wordMatchLen (line, "const", 4) || wordMatchLen (line, "final", 5))
{
heredoc = parseVariableOrConstant (skipWord (line), infunction, K_CONST);
heredoc = parseVariableOrConstant (skipWord (line), parent, K_CONST);
}

tagEntryInfo *e;
Expand All @@ -760,13 +829,13 @@ static bool parseVimLine (const unsigned char *line, int infunction)
return readNextLine;
}

static void parseVimFile (const unsigned char *line)
static void parseVimFile (const unsigned char *line, int parent)
{
bool readNextLine = true;

while (line != NULL)
{
readNextLine = parseVimLine (line, false);
readNextLine = parseVimLine (line, parent);

if (readNextLine)
line = readVimLine ();
Expand Down Expand Up @@ -850,6 +919,8 @@ static void findVimTags (void)
const unsigned char *line;
/* TODO - change this into a structure */

vim9script = false;

line = readVimLine ();

if (line == NULL)
Expand All @@ -863,7 +934,7 @@ static void findVimTags (void)
}
else
{
parseVimFile (line);
parseVimFile (line, CORK_NIL);
}
}

Expand Down

0 comments on commit 6c5cba0

Please sign in to comment.