aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorZyX <kp-pav@yandex.ru>2017-11-03 11:38:59 +0300
committerZyX <kp-pav@yandex.ru>2017-11-06 01:17:38 +0300
commitb9d5aea073521f3278bea257be306b7ac2b8d83c (patch)
tree28f72194cd71d676dc4589ab61c3a483091f773c /src
parentd98199de9c2969d430ba489187ffa02d8c489dea (diff)
downloadrneovim-b9d5aea073521f3278bea257be306b7ac2b8d83c.tar.gz
rneovim-b9d5aea073521f3278bea257be306b7ac2b8d83c.tar.bz2
rneovim-b9d5aea073521f3278bea257be306b7ac2b8d83c.zip
api/vim: Create part of nvim_parse_expression function
Diffstat (limited to 'src')
-rw-r--r--src/nvim/api/vim.c106
1 files changed, 105 insertions, 1 deletions
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index 9daa2fb398..446a049897 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -33,6 +33,8 @@
#include "nvim/syntax.h"
#include "nvim/getchar.h"
#include "nvim/os/input.h"
+#include "nvim/viml/parser/expressions.h"
+#include "nvim/viml/parser/parser.h"
#define LINE_BUFFER_SIZE 4096
@@ -897,6 +899,12 @@ theend:
///
/// Use only "m" to parse like for "<C-r>=", only "E" to
/// parse like for ":echo", empty string for ":let".
+/// @param[in] highlight If true, return value will also include "highlight"
+/// key containing array of 4-tuples (arrays) (Integer,
+/// Integer, Integer, String), where first three numbers
+/// define the highlighted region and represent line,
+/// starting column and ending column (latter exclusive:
+/// one should highlight region [start_col, end_col)).
///
/// @return AST: top-level dectionary holds keys
///
@@ -946,9 +954,105 @@ theend:
/// "fvalue": Float, floating-point value for "Float" nodes.
/// "svalue": String, value for "SingleQuotedString" and
/// "DoubleQuotedString" nodes.
-Dictionary nvim_parse_expression(String expr, String flags, Error *err)
+Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight,
+ Error *err)
FUNC_API_SINCE(4)
{
+ int pflags = 0;
+ for (size_t i = 0 ; i < flags.size ; i++) {
+ switch (flags.data[i]) {
+ case 'm': { pflags |= kExprFlagsMulti; break; }
+ case 'E': { pflags |= kExprFlagsDisallowEOC; break; }
+ default: {
+ api_set_error(err, kErrorTypeValidation, "Invalid flag: '%c' (%u)",
+ flags.data[i], (unsigned)flags.data[i]);
+ return (Dictionary)ARRAY_DICT_INIT;
+ }
+ }
+ }
+ ParserLine plines[] = {
+ {
+ .data = expr.data,
+ .size = expr.size,
+ .allocated = false,
+ },
+ { NULL, 0, false },
+ };
+ ParserLine *plines_p = plines;
+ ParserHighlight colors;
+ kvi_init(colors);
+ ParserHighlight *const colors_p = (highlight ? &colors : NULL);
+ ParserState pstate;
+ viml_parser_init(
+ &pstate, parser_simple_get_line, &plines_p, colors_p);
+ ExprAST east = viml_pexpr_parse(&pstate, pflags);
+
+ const size_t dict_size = (
+ 1 // "ast"
+ + (size_t)(east.err.arg != NULL) // "error"
+ + (size_t)highlight // "highlight"
+ );
+ Dictionary ret = {
+ .items = xmalloc(dict_size * sizeof(ret.items[0])),
+ .size = 0,
+ .capacity = dict_size,
+ };
+ ret.items[ret.size++] = (KeyValuePair) {
+ .key = STATIC_CSTR_AS_STRING("ast"),
+ .value = NIL,
+ };
+ if (east.err.arg != NULL) {
+ Dictionary err_dict = {
+ .items = xmalloc(2 * sizeof(err_dict.items[0])),
+ .size = 2,
+ .capacity = 2,
+ };
+ err_dict.items[0] = (KeyValuePair) {
+ .key = STATIC_CSTR_AS_STRING("message"),
+ .value = STRING_OBJ(cstr_to_string(east.err.arg)),
+ };
+ err_dict.items[1] = (KeyValuePair) {
+ .key = STATIC_CSTR_AS_STRING("arg"),
+ .value = STRING_OBJ(((String) {
+ .data = xmemdup(east.err.arg, (size_t)east.err.arg_len),
+ .size = (size_t)east.err.arg_len,
+ })),
+ };
+ ret.items[ret.size++] = (KeyValuePair) {
+ .key = STATIC_CSTR_AS_STRING("error"),
+ .value = DICTIONARY_OBJ(err_dict),
+ };
+ }
+ if (highlight) {
+ Array hl = (Array) {
+ .items = xmalloc(kv_size(colors) * sizeof(hl.items[0])),
+ .capacity = kv_size(colors),
+ .size = kv_size(colors),
+ };
+ for (size_t i = 0 ; i < kv_size(colors) ; i++) {
+ const ParserHighlightChunk chunk = kv_A(colors, i);
+ Array chunk_arr = (Array) {
+ .items = xmalloc(4),
+ .capacity = 4,
+ .size = 4,
+ };
+ chunk_arr.items[0] = INTEGER_OBJ((Integer)chunk.start.line);
+ chunk_arr.items[1] = INTEGER_OBJ((Integer)chunk.start.col);
+ chunk_arr.items[2] = INTEGER_OBJ((Integer)chunk.end_col);
+ chunk_arr.items[3] = STRING_OBJ(cstr_to_string(chunk.group));
+ hl.items[i] = ARRAY_OBJ(chunk_arr);
+ }
+ ret.items[ret.size++] = (KeyValuePair) {
+ .key = STATIC_CSTR_AS_STRING("highlight"),
+ .value = ARRAY_OBJ(hl),
+ };
+ }
+
+ // FIXME: populate AST
+
+ assert(ret.size == ret.capacity);
+ viml_pexpr_free_ast(east);
+ viml_parser_destroy(&pstate);
return (Dictionary)ARRAY_DICT_INIT;
}