const PREC = {
PAREN: 14, POWER: 12, UNARY: 11, TIMES: 10, PLUS: 9, CONCAT: 8, SHIFT: 7, BIT_AND: 6, BIT_NOT: 5, BIT_OR: 4, COMPARE: 3, AND: 2, OR: 1, TERNARY: -1, };
const IDENTIFIER = /[A-Za-z_\u00A1-\uFFFF][A-Za-z0-9_\u00A1-\uFFFF′⁀-⁑₀-₉]*/;
const UNDEFINE_ARG = new RegExp(`[ \\t]+${IDENTIFIER.source}\\*?`);
const K = {
axes: /(x|y|z|x2|y2|cb|r|t|u|v|xy|vx|vy|vz)/, zaxes: /(x|y|z|x2|y2)?/,
l: reg("left", 1),
r: reg("right", 1),
c: reg("center", 1),
};
const dataSeparator = ($) =>
seq(
key("separator", 3),
choice(key("whitespace", 5), "tab", "comma", field("separator", $._expression)),
);
const fillStyleOpt = ($) => seq($._fs, $.fill_style); const atPos = ($) => seq(alias("at", "kw_fn"), $.position); const offsetPos = ($) => seq(key("offset", 3), $.position);
const TERM_NAME = token(
choice(
reg("cairolatex", 3), reg("canvas", 3), reg("cgm", 2), reg("context", 2),
reg("domterm", 2), reg("dumb", 2), reg("dxf", 2), reg("emf", 2),
reg("epscairo", 1), reg("epslatex", 4), reg("fig", 1), reg("gif", 1),
reg("hpgl", 1), reg("jpeg", 1),
reg("kittycairo", 3), reg("kittygd", -1),
reg("lua", 1), reg("pcl5", 2), reg("pdfcairo", 2), reg("pict2e", 2),
"png", reg("pngcairo", 4), reg("postscript", 2),
reg("pslatex", 3), reg("pstex", -1), reg("pstricks", 4),
reg("qt", 1), reg("sixelgd", 1), reg("svg", 2),
/k[cm]-tek40xx/, reg("tek40xx", 5), reg("tek410x", 5),
reg("texdraw", 3), reg("tikz", 2), reg("tkcanvas", 2), reg("unknown", 1),
reg("vttek", 1), reg("webp", 1), reg("wxt", 2), reg("x11", 1),
reg("xterm", 2),
),
);
module.exports = grammar({
name: "gnuplot",
externals: ($) => [
$.datablock_start,
$.datablock_end,
$.cmd_fit_kw, $.cmd_plot_kw, $.cmd_splot_kw, $.cmd_pause_kw, $.cmd_print_kw, $.cmd_help_kw, $.cmd_load_kw, $.kw_plt_st, $.kw_cmd_bare, $.kw_cmd_optexpr, $.kw_cmd_exit, $.kw_cmd_expr, $.kw_sa, $.kw_lt, $.kw_lc, $.kw_dt, $.kw_pt, $.kw_ps,
$.kw_fs, $.kw_fc, $.kw_tc,
$.kw_g_arg, $.kw_g_argv, $.kw_g_flag, $.kw_g_mod, $.kw_g_coord, $.kw_g_axisflag,
$.kw_g_axisrange,
$._gval_sep,
$._gval_bind,
$.unit_pi,
$._gval_tail,
$.kw_filter_if,
],
extras: ($) => [$.comment, /\s|\\|;/],
word: ($) => $.identifier,
conflicts: ($) => [
[$.plot_element, $.style_opts],
[$._plot_data_expr, $._expression],
[$.plot_element, $._expression],
[$.plot_style],
[$.assignment, $._var_rhs],
[$._tag_atom, $._expression],
[$._command, $.multiplot_block],
[$._gexprs, $._view_slot],
],
rules: {
source_file: ($) => repeat($._statement),
_sa: ($) => seq(alias($.kw_sa, "sa"), $._expression),
_lt: ($) => alias($.kw_lt, "lt"),
_lc: ($) => alias($.kw_lc, "lc"),
_dt: ($) => alias($.kw_dt, "dt"),
_pt: ($) => alias($.kw_pt, "pt"),
_ps: ($) => alias($.kw_ps, "ps"),
_fs: ($) => alias($.kw_fs, "fs"),
_fc: ($) => alias($.kw_fc, "fc"),
_tc: ($) => alias($.kw_tc, "tc"),
_gexprs: ($) =>
prec.right(
seq(
$._expression,
repeat(
seq(
",",
optional(alias($.kw_g_coord, "coord")),
choice($._expression, $.range_block),
),
),
),
),
tuple: ($) =>
prec.dynamic(-1, surround("()", seq($._gexprs, repeat($._gexprs)))),
_gopt_item: ($) =>
choice(
alias($.kw_g_flag, "flag"),
prec.right(seq(alias($.kw_g_mod, "mod"), optional(seq(",", $._gexprs)))),
prec.right(seq(alias($.kw_g_arg, "arg"), optional(seq($._gval_bind, choice($._gexprs, $.tuple))))),
seq(alias($.kw_g_argv, "arg"), $._gval_bind, choice($._gexprs, $.tuple)),
prec.right(seq(alias($.kw_g_coord, "coord"), optional(seq($._gval_bind, $._gexprs)))),
$._gexprs,
$.tuple,
$.range_block,
),
_gopts: ($) => prec.left(repeat1($._gopt_item)),
_gopts_style: ($) =>
prec.left(
repeat1(
choice(
$._gopt_item,
alias($.kw_g_axisflag, "flag"),
prec.right(seq($.style_opts, optional(seq(",", $.style_opts)))),
$.background,
$.mono_color,
$.line_drawing_method,
seq("position", $.position),
seq("name", $._expression),
key("eps", undefined, "mod"),
key("reset", undefined, "mod"),
key("raise", undefined, "flag", 1),
key("input", undefined),
seq(
key("animate", undefined),
repeat(choice(
seq(alias("delay", "arg"), $._expression),
seq(alias("loop", "arg"), $._expression),
seq(alias("quality", "arg"), $._expression),
)),
),
key("noanimate", undefined, "flag"),
),
),
),
_statement: ($) => choice($._command, $.assignment, $.macro),
_command: ($) =>
choice(
$.cmd_bind,
$.cmd_bare,
$.cmd_call,
$.cmd_do,
$.cmd_expr,
$.cmd_exit,
$.cmd_fit,
$.cmd_help,
$.cmd_history,
$.cmd_if,
$.cmd_import,
$.cmd_load,
$.cmd_opt_expr,
$.cmd_pause,
$.cmd_plot,
$.cmd_print,
$.cmd_reset,
$.cmd_save,
$.cmd_set,
$.cmd_show,
$.cmd_splot,
$.cmd_stats,
$.cmd_system,
$.cmd_test,
$.cmd_undefine,
$.cmd_unset,
$.cmd_vfill,
$.cmd_while,
$.multiplot_block,
alias($._unset_multiplot, $.cmd_unset),
),
assignment: ($) =>
choice($.def_var, $.def_func, $.def_array, $.def_datablock),
def_var: ($) => prec.right(seq($.identifier, "=", $._var_rhs)),
_var_rhs: ($) => prec.right(choice($.def_var, $._expression)),
def_array: ($) =>
choice(
seq($.array, "=", $._expression),
seq("array", $.array, optional(seq("=", $._array_literal))),
seq("array", $.identifier, "=", choice($._array_literal, $._expression)),
),
_array_literal: ($) => surround("[]", sep(",", optional($._expression))),
def_func: ($) => seq($.function, "=", $._expression),
def_datablock: ($) =>
prec(
1,
seq(
field("name", $.datablock),
"<<",
field("start", $.datablock_start),
repeat($._expression),
field("end", $.datablock_end),
),
),
macro: ($) => token(seq("@", IDENTIFIER)),
cmd_bind: ($) =>
prec.right(
seq(
alias("bind", "cmd"),
optional(key("allwindows", 3, "mod")),
optional(
seq(
field("key", $._expression),
optional(field("commands", $._expression)),
),
),
),
),
cmd_bare: ($) =>
seq(
alias($.kw_cmd_bare, "cmd"),
optional(seq($._gval_tail, sep(",", $.plot_element))),
),
cmd_opt_expr: ($) =>
seq(
alias($.kw_cmd_optexpr, "cmd"),
optional(seq($._gval_sep, choice($._expression, alias("all", "mod")))),
),
cmd_expr: ($) => seq(alias($.kw_cmd_expr, "cmd"), $._expression),
cmd_call: ($) =>
prec.right(seq(alias("call", "cmd"), $._expression, repeat($._expression))),
cmd_do: ($) => seq("do", $.for_block, surround("{}", repeat($._statement))),
cmd_exit: ($) =>
prec.left(
seq(
alias($.kw_cmd_exit, "cmd"),
optional(
choice(
alias("gnuplot", "mod"),
seq(choice("message", "status"), optional($._expression)),
),
),
),
),
cmd_fit: ($) =>
seq(
alias($.cmd_fit_kw, "cmd"),
optional($.range_block),
field("func", $.function),
field("data", $._expression),
optional($.datafile_modifiers),
repeat(
choice(
"unitweights",
alias(/(y|xy|z)err(o(r(s)?)?)?/, "errors"),
seq("errors", sep(",", $._expression)),
),
),
alias("via", "kw_fn"),
choice(
field("parameter_file", $._expression),
field("var", seq($._expression, repeat1(seq(",", $._expression)))),
),
),
cmd_help: ($) => prec.right(seq(alias($.cmd_help_kw, "cmd"), optional($._expression))),
cmd_history: ($) =>
prec.right(
seq(
key("history", 4, "cmd"),
optional(
repeat1(
choice(
$._expression, key("append", 3),
key("quiet", 2),
key("numbers", 3),
key("trim", 2),
key("full", 4),
),
),
),
),
),
cmd_import: ($) =>
seq(
alias("import", "cmd"),
$.function,
alias("from", "kw_fn"),
$.string_literal,
),
cmd_if: ($) =>
prec.left(
seq(
alias("if", "kw_cond"),
field("conditions", surround("()", sep(",", choice($.assignment, $._expression)))),
choice(
repeat1($._statement),
seq(
surround("{}", repeat($._statement)),
repeat(
seq(
alias("else", "kw_cond"),
alias("if", "kw_cond"),
repeat1(field("conditions", surround("()", $._expression))),
surround("{}", repeat($._statement)),
),
),
),
),
optional(seq(alias("else", "kw_cond"), surround("{}", repeat($._statement)))),
),
),
cmd_load: ($) => seq(alias($.cmd_load_kw, "cmd"), $._expression),
cmd_pause: ($) =>
prec.right(
seq(
alias($.cmd_pause_kw, "cmd"),
choice(
seq(
field("time", $._expression),
optional(field("str", $._expression)),
),
seq(
"mouse",
sep(",", $.endcondition),
optional(field("str", $._expression)),
),
),
),
),
endcondition: ($) =>
choice(
alias("keypress", "mod"),
alias("button1", "mod"),
alias("button2", "mod"),
alias("button3", "mod"),
alias("close", "mod"),
alias("any", "mod"),
),
cmd_plot: ($) =>
seq(alias($.cmd_plot_kw, "cmd"), optional("sample"), sep(",", $.plot_element)),
plot_element: ($) =>
seq(
prec.left(
1,
seq(
optional($.for_block),
repeat(field("sample", $.range_block)),
choice(
seq(
sep(",", $.assignment),
optional(","),
$._expression, optional($.datafile_modifiers),
),
seq(
field("function", choice($.function, $.unary_expression)),
optional($.datafile_modifiers),
),
seq(
field("data", choice($._plot_data_expr, "keyentry")),
optional($.datafile_modifiers),
),
"newspiderplot",
seq(
"newhistogram",
repeat(
choice(
field("title", $.string_literal),
$.fontspec,
$._textcolor,
seq($._lt, field("lt", $._expression)),
fillStyleOpt($),
seq(alias("at", "kw_fn"), field("at", $._expression)),
),
),
),
),
),
),
repeat(
choice(
seq(
alias("axes", "attr"),
alias(choice("x1y1", "x2y2", "x1y2", "x2y1"), "axes_opts"),
),
choice(
key("notitle", 3, "attr"),
prec.left(
seq(
key("title", 1, "attr"),
choice(
field("title", $._expression),
seq(
field("title", key("columnheader", 3, $.columnheader)),
optional(surround("()", field("column", $._expression))),
),
),
repeat(
choice(
seq(alias("at", "kw_fn"), choice("beginning", "end", $.position)),
key("enhanced", 3, "flag", 1),
),
),
),
),
),
seq(
alias("watch", "attr"),
choice(
alias("mouse", "mod"),
seq(
field("target", choice($.function, $.identifier)),
"=",
field("value", $._expression),
optional(seq(alias("label", "attr"), field("label", $._expression))),
),
),
),
alias("nogrid", "flag"), seq(key("whiskerbars", 7), optional(field("fraction", $._expression))),
$._plot_filter,
field("with", seq(key("with", 1, "attr"), $.plot_style)),
$.style_opts,
),
),
),
_hsteps_opts: ($) =>
repeat1(
choice(
key("baseline", 4, "mod"),
key("forward", 2, "mod"),
key("backward", 2, "mod"),
key("link", 4, "mod", 1),
prec.dynamic(
1,
seq(
key("offset", 3, "mod"),
field(
"offset",
choice(
$.number,
$.identifier,
$.parenthesized_expression,
alias(
seq(
alias(/[-+]/, $.operator),
choice($.number, $.identifier, $.parenthesized_expression),
),
$.unary_expression,
),
),
),
),
),
),
),
_plot_data_expr: ($) =>
prec.left(
choice(
$.identifier,
$.array,
$.subscript,
$.datablock,
$.number,
$.complex,
$.string_literal,
$.sum_block,
$.parenthesized_expression,
$.binary_expression,
$.ternary_expression,
),
),
_plot_filter: ($) =>
seq(alias($.kw_filter_if, "attr"), field("filter", $._expression)),
plot_style: ($) =>
choice(
seq(key("hsteps", 2, "plt_st"), optional($._hsteps_opts)),
prec.left(
choice(
seq(
alias($.kw_plt_st, "plt_st"),
optional(seq(alias("at", "kw_fn"), key("base", 1))),
),
seq(key("labels", 3, "plt_st"), optional($.label_opts)),
seq(key("vectors", 3, "plt_st"), optional($.arrow_opts)),
seq(
key("isosurface", 10, "plt_st"),
optional(seq("level", $._expression)),
),
key("candlesticks", 12, "plt_st"),
seq(key("ellipses", 8, "plt_st"), optional($.ellipse)),
seq(
key("filledcurves", 7, "plt_st"),
optional(
choice(
"closed",
"between",
seq(
optional(choice("above", "below")),
optional(
seq(
alias(
choice("x1", "x2", "y1", "y2", "y", "r"),
"axis",
),
optional(seq("=", $._expression)),
),
),
),
),
),
),
seq(
key("fillsteps", 9, "plt_st"),
optional(choice("above", "below")),
optional(seq(alias("y", "axis"), "=", $._expression)),
),
seq(key("image", 3, "plt_st"), optional("pixels")),
seq(key("pm3d", 4, "plt_st"), optional(alias($._pm3d, $.pm3d))),
),
),
),
cmd_print: ($) =>
seq(
alias($.cmd_print_kw, "cmd"),
optional($.for_block),
sep(",", $._expression),
),
cmd_reset: ($) =>
prec.right(seq(alias("reset", "cmd"), optional(choice(alias("bind", "mod"), alias("errors", "mod"), alias("session", "mod"))))),
cmd_save: ($) =>
seq(
key("save", 2, "cmd"),
optional(
choice(
key("functions", 3),
key("variables", 3),
key("changes", 6),
key("terminal", 3, "mod"),
alias("set", "mod"),
alias("fit", "mod"),
key("datablocks", 4),
),
),
field("filename", $._expression),
optional("append"),
),
cmd_set: ($) =>
seq(
seq(key("set", 2, "cmd"), optional($.for_block)),
$._argument_set_show,
),
_gopt_body: ($) => seq($._gval_sep, $._gopts),
_gopt_body_style: ($) => seq($._gval_sep, $._gopts_style),
_argument_set_show: ($) =>
prec.right(
choice(
$.angles,
$.arrow,
$.autoscale,
$.border,
$.boxwidth,
$.boxdepth,
$.color,
$.colormap,
$.colorsequence,
$.clip,
$.cntrlabel,
$.cntrparam,
$.colorbox,
$.contour,
$.cornerpoles,
$.contourfill,
$.dashtype,
$.datafile,
$.decimalsign,
$.dgrid3d,
$.dummy,
seq(
key("encoding", 3, "opt"),
field("arg_opts", optional(alias($._gopt_body, $.encoding))),
),
seq(
key1("opt", "errorbars", /|/, reg("bars", 1)),
field("arg_opts", optional(alias($._gopt_body_style, $.errorbars))),
),
seq(alias("fit", "opt"), field("arg_opts", optional(alias($._gopt_body, $.fit)))),
seq(key("format", 4, "opt"), field("arg_opts", optional(alias($._gopt_body_style, $.format)))),
$.grid,
seq(
key("hidden3d", 3, "opt"),
field("arg_opts", optional(alias($._gopt_body, $.hidden3d))),
),
seq(key("history", 3, "opt"), field("arg_opts", optional(alias($._gopt_body, $.history)))),
seq(
key("isosamples", 3, "opt"),
field("arg_opts", optional(alias($._gopt_body, $.isosamples))),
),
seq(
key("isosurface", 7, "opt"),
field("arg_opts", optional(alias($._gopt_body, $.isosurface))),
),
alias("isotropic", "opt"),
seq(alias("jitter", "opt"), field("arg_opts", optional(alias($._gopt_body, $.jitter)))),
$.key,
$.label,
$.linetype,
seq(alias("link", "opt"), field("arg_opts", optional($.link))),
$.loadpath,
seq(alias("locale", "opt"), field("arg_opts", optional(alias($._gopt_body, $.locale)))),
$.logscale,
$.mapping,
$.margin,
seq(alias("micro", "opt"), field("arg_opts", optional($.micro))),
key("minussign", 5, "opt"),
$.monochrome,
seq(key("mouse", 2, "opt"), field("arg_opts", optional(alias($._gopt_body, $.mouse)))),
$.mxtics,
$.nonlinear,
$.object,
seq(key("offsets", 3, "opt"), field("arg_opts", optional(alias($._gopt_body, $.offsets)))),
seq(key("origin", 2, "opt"), field("arg_opts", optional(alias($._gopt_body, $.origin)))),
seq(key("output", 1, "opt"), field("arg_opts", optional(alias($._gopt_body, $.output)))),
seq(
alias("overflow", "opt"),
field("arg_opts", optional($.overflow)),
),
$.palette,
key("parametric", 2, "opt"),
$.paxis,
$.pixmap,
$.pm3d,
$.pointintervalbox,
$.pointsize,
seq(key("polar", 3, "opt"), field("arg_opts", optional($.polar))),
seq(key("print", 2, "opt"), field("arg_opts", optional(alias($._gopt_body, $.print)))),
seq(alias("psdir", "opt"), field("arg_opts", optional(alias($._gopt_body, $.psdir)))),
key("raxis", 2, "opt"),
seq(alias("rgbmax", "opt"), field("arg_opts", optional(alias($._gopt_body, $.rgbmax)))),
seq(key("samples", 3, "opt"), field("arg_opts", optional(alias($._gopt_body, $.samples)))),
seq(key("size", 2, "opt"), field("arg_opts", optional(alias($._gopt_body, $.size)))),
key("spiderplot", 6, "opt"),
$.style,
seq(key("surface", 2, "opt"), field("arg_opts", optional(alias($._gopt_body, $.surface)))),
$.table,
$.terminal,
seq(
alias("termoption", "opt"),
field("arg_opts", optional(alias($._gopt_body_style, $.termoption))),
),
seq(alias("theta", "opt"), field("arg_opts", optional(alias($._gopt_body, $.theta)))),
seq(key("tics", -1, "opt"), field("arg_opts", optional($.tics))),
seq(
key("timestamp", 5, "opt"),
field("arg_opts", optional(alias($._gopt_body_style, $.timestamp))),
),
seq(key("timefmt", 5, "opt"), field("arg_opts", optional(alias($._gopt_body, $.timefmt)))),
$.title,
seq(alias("vgrid", "opt"), field("arg_opts", optional($.vgrid))),
seq(key("view", 2, "opt"), field("arg_opts", optional($.view))),
seq(key("walls", -1, "opt"), field("arg_opts", optional(alias($._gopt_body_style, $.walls)))),
$.xdata,
$.xdtics,
$.xlabel,
$.xmtics,
$.xrange,
$.xtics,
$.xyplane,
seq(key("zero", 1, "opt"), field("arg_opts", optional(alias($._gopt_body, $.zero)))),
$.zeroaxis,
prec.dynamic(
-1,
prec.right(seq(field("opt", $.identifier), optional(seq($._gval_sep, $._gopts)))),
),
),
),
angles: ($) =>
prec.right(seq(key("angles", 2, "opt"), optional(seq($._gval_sep, $._gopts)))),
arrow: ($) =>
prec.left(
seq(
key("arrow", 3, "opt"),
optional(
seq(
optional(field("tag", $._expression)),
repeat1(
choice(
seq(
optional(seq(alias("from", "kw_fn"), $.position)),
alias(/r?to/, "kw_fn"),
$.position,
),
seq(
alias("from", "kw_fn"),
$.position,
key("length", 3),
field("length", $._expression),
key("angle", 2),
field("angle", $._expression),
),
$.arrow_opts,
),
),
),
),
),
),
autoscale: ($) =>
prec.right(
seq(
key("autoscale", 4, "opt"),
optional(
seq(
$._gval_sep,
prec.left(
repeat1(
choice($._gopt_item, alias($.kw_g_axisrange, "arg")),
),
),
),
),
),
),
border: ($) =>
prec.right(seq(key("border", 3, "opt"), optional(seq($._gval_sep, $._gopts_style)))),
boxwidth: ($) =>
prec.right(seq(key("boxwidth", 3, "opt"), optional(seq($._gval_sep, $._gopts)))),
boxdepth: ($) =>
prec.right(seq(alias("boxdepth", "opt"), optional(seq($._gval_sep, $._gopts)))),
color: ($) => alias("color", "opt"),
colormap: ($) =>
prec.right(seq(alias("colormap", "opt"), optional(seq($._gval_sep, $._gopts)))),
colorsequence: ($) =>
prec.right(seq(alias("colorsequence", "opt"), optional(seq($._gval_sep, $._gopts)))),
clip: ($) => prec.right(seq(alias("clip", "opt"), optional(seq($._gval_sep, $._gopts)))),
cntrlabel: ($) =>
prec.right(seq(key("cntrlabel", 5, "opt"), optional(seq($._gval_sep, $._gopts_style)))),
cntrparam: ($) =>
prec.right(seq(key("cntrparam", 5, "opt"), optional(seq($._gval_sep, $._gopts)))),
colorbox: ($) =>
prec.right(seq(key("colorbox", 6, "opt"), optional(seq($._gval_sep, $._gopts_style)))),
contour: ($) =>
prec.right(seq(key("contours", 5, "opt"), optional(seq($._gval_sep, $._gopts)))),
cornerpoles: ($) => key("cornerpoles", 7, "opt"),
contourfill: ($) =>
prec.right(seq(alias("contourfill", "opt"), optional(seq($._gval_sep, $._gopts)))),
dashtype: ($) =>
prec.left(
seq(
alias($.kw_dt, "opt"),
field("tag", $._expression),
optional($.dash_opts),
),
),
datafile: ($) =>
prec.left(
seq(
key("datafile", 5, "opt"),
repeat(
choice(
key("columnheaders", -3, "flag", 1),
key("fortran", 4, "mod"),
alias("nofpe_trap", "flag"),
seq(key("missing", 4), field("missing", $._expression)),
dataSeparator($),
seq(
key("commentschars", 3),
optional(field("srt", $._expression)),
),
$.binary_options,
),
),
),
),
decimalsign: ($) =>
prec.right(seq(key("decimalsign", 3, "opt"), optional(seq($._gval_sep, $._gopts)))),
dgrid3d: ($) =>
prec.right(seq(key("dgrid3d", 2, "opt"), optional(seq($._gval_sep, $._gopts)))),
dummy: ($) =>
prec.right(seq(key("dummy", 2, "opt"), optional(seq($._gval_sep, $._dummy_vars)))),
_dummy_vars: ($) =>
prec.right(
choice(
seq($.identifier, repeat($._dummy_slot)),
repeat1($._dummy_slot),
),
),
_dummy_slot: ($) => prec.right(seq(",", optional($.identifier))),
grid: ($) =>
prec.right(seq(key("grid", 1, "opt"), optional(seq($._gval_sep, $._gopts_style)))),
key: ($) =>
prec.right(seq(key("key", 1, "opt"), optional(seq($._gval_sep, $._gopts_style)))),
label: ($) =>
prec.right(
seq(
key("label", 3, "opt"),
optional(prec.dynamic(2, field("tag", $._tag_atom))),
optional($.label_opts),
),
),
linetype: ($) =>
prec.right(seq(alias($.kw_lt, "opt"), optional(seq($._gval_sep, $._gopts_style)))),
link: ($) =>
repeat1(
choice(
alias(choice("x2", "y2"), "axis"),
seq(alias("via", "kw_fn"), $._expression, "inverse", $._expression),
),
),
loadpath: ($) =>
prec.right(seq(key("loadpath", 4, "opt"), optional(seq($._gval_sep, $._gopts)))),
logscale: ($) => {
const axis = choice("x", "y", "z", "x2", "y2", "cb", "r");
return seq(
key("logscale", 3, "opt"),
optional(
prec.left(
seq(
alias(token(repeat1(axis)), "axis"),
optional(field("base", $._expression)),
),
),
),
);
},
mapping: ($) =>
prec.right(seq(key("mapping", 3, "opt"), optional(seq($._gval_sep, $._gopts)))),
margin: ($) =>
prec.right(
seq(key1("opt", /(l|r|t|b)?/, reg("margins", 3)), optional(seq($._gval_sep, $._gopts))),
),
_margin: ($) =>
prec.left(
choice(
seq(optional(seq(optional(alias("at", "kw_fn")), alias("screen", "coord"))), $._expression),
seq(
field("lm", $._expression),
",",
field("rm", $._expression),
",",
field("bm", $._expression),
",",
field("tm", $._expression),
),
),
),
micro: ($) => prec.right(seq(alias("micro", "opt"), optional(seq($._gval_sep, $._gopts)))),
monochrome: ($) =>
prec.left(seq(key("monochrome", 4, "opt"), optional($.line_style))),
multiplot: ($) =>
seq(
key("multiplot", 5, "opt"),
repeat(
choice(
seq(
key("title", 1),
field("title", $._expression),
optional($.fontspec),
optional(key("enhanced", undefined, "flag", 1)),
),
seq(
"layout",
field("rows", $._expression),
",",
field("cols", $._expression),
),
choice(alias("rowsfirst", "mod"), alias("columnsfirst", "mod")),
choice(alias("downwards", "mod"), alias("upwards", "mod")),
seq(
"scale",
field("xscale", $._expression),
optional(seq(",", field("yscale", $._expression))),
),
offsetPos($),
seq("margins", alias($._margin, $.margin)), seq(
"spacing",
field("xspacing", $._expression),
optional(seq(",", field("yspacing", $._expression))),
),
alias(choice("previous", "next"), "mod"),
),
),
),
multiplot_block: ($) =>
choice(
prec.dynamic(
1,
seq(
alias($._set_multiplot, $.cmd_set),
repeat($._statement),
alias($._unset_multiplot, $.cmd_unset),
),
),
prec.right(
seq(alias($._set_multiplot, $.cmd_set), repeat($._statement)),
),
),
_set_multiplot: ($) => seq(key("set", 2, "cmd"), $.multiplot),
_unset_multiplot: ($) => seq(key("unset", 3, "cmd"), $.multiplot),
mxtics: ($) =>
prec.right(
seq(
key1("opt", "m", K.axes, reg("tics", -1)),
optional(seq($._gval_sep, $._gopts)),
),
),
nonlinear: ($) =>
seq(
key("nonlinear", 5, "opt"),
alias(K.axes, "axis"),
alias("via", "kw_fn"),
$._expression,
"inverse",
$._expression,
),
object: ($) =>
prec.right(seq(key("object", 3, "opt"), optional(seq($._gval_sep, $._gopts_style)))),
overflow: ($) => choice(alias("float", "mod"), "NaN", alias("undefined", "mod")),
palette: ($) =>
prec.right(
seq(
key("palette", 3, "opt"),
optional(
seq(
$._gval_sep,
prec.left(
repeat1(
choice(
$._gopt_item,
prec.right(
seq(
alias("file", "arg"),
field("filename", $._expression),
optional($.datafile_modifiers),
),
),
seq(key("model", 2), choice("RGB", "CMY", "HSV")),
"viridis",
),
),
),
),
),
),
),
_paxis_label: ($) =>
prec.right(seq(key("label", 3), optional($.label_opts))),
paxis: ($) =>
prec.left(
seq(
alias("paxis", "opt"),
field("axisno", $._expression),
optional(
seq(
key("range", 3),
$.range_block,
repeat(
choice(
key("reverse", 3, "flag", 1),
key("writeback", 3, "flag", 1),
key("extend", 3, "flag", 1),
"restore",
),
),
),
),
optional(seq(key("tics", 3), optional(seq($._gval_sep, $.tics_opts)))),
optional($._paxis_label),
optional(offsetPos($)),
),
),
pixmap: ($) =>
prec.right(seq(key("pixmap", 4, "opt"), optional(seq($._gval_sep, $._gopts)))),
pm3d: ($) => seq(alias("pm3d", "opt"), optional($._pm3d)),
_pm3d: ($) =>
repeat1(
choice(
seq(alias("at", "kw_fn"), alias(token(/[bst]{1,6}/), "mod")),
seq(
key("interpolate", 6),
field("steps", $._expression),
",",
field("between", $._expression),
),
choice(
alias(
/scans(auto(m(a(t(i(c)?)?)?)?)?|forward|backward)/,
"scanorder",
),
seq(key("depthorder", 3), optional("base")),
key("hidden3d", 2, "flag", 1),
),
seq(alias("flush", "arg"), choice("begin", "center", "end")),
key("ftriangles", undefined, "flag", 1),
choice(seq("clip", optional(alias("z", "axis"))), "clip1in", "clip4in"),
key("clipcb", undefined, "flag", 1),
seq("zclip", $.range_block),
seq(
"corners2color",
alias(/(geo|har)?mean|rms|m(edian|in|ax)|c(1|2|3|4)/, "c2c"),
),
seq(
key("lighting", 5, "flag", 1),
repeat(
choice(
seq("primary", field("fraction", $._expression)),
seq(key("specular", 4), field("fraction", $._expression)),
seq("spec2", field("fraction", $._expression)),
),
),
),
seq(
key("spotlight", 4, "arg"),
repeat(
choice(
seq(key("rgbcolor", 3), field("color", $._expression)),
seq("rot_x", field("angle", $._expression)),
seq("rot_z", field("angle", $._expression)),
seq("Phong", field("exponent", $._expression)),
"default",
),
),
),
seq(
key("border", undefined, "flag", 1),
optional("retrace"),
optional($.style_opts),
),
choice(alias("implicit", "mod"), alias("explicit", "mod")),
"map",
),
),
pointintervalbox: ($) =>
prec.right(seq(key("pointintervalbox", 8, "opt"), optional(seq($._gval_sep, $._gopts)))),
pointsize: ($) =>
prec.right(seq(key("pointsize", 3, "opt"), optional(seq($._gval_sep, $._gopts)))),
polar: ($) =>
prec.right(seq(alias("grid", "mod"), optional(seq($._gval_sep, $._gopts)))),
style: ($) =>
prec.left(
1,
seq(
key("style", 2, "opt"),
optional(
choice(
seq(key("arrow", 3, "st_opt"), optional(seq($._gval_sep, $._gopts_style))),
seq(alias("boxplot", "st_opt"), optional(seq($._gval_sep, $._gopts_style))),
seq(
key("data", 1, "st_opt"),
choice(
$.plot_style,
key("errorbars", 1, "plt_st"),
key("errorlines", 6, "plt_st"),
),
),
seq(key("function", 1, "st_opt"), $.plot_style),
seq(key("histogram", 4, "st_opt"), optional(seq($._gval_sep, $._gopts_style))),
seq(key("line", 1, "st_opt"), $.line_style),
seq(key("circle", -2, "st_opt"), optional(seq($._gval_sep, $._gopts_style))),
seq(key("rectangle", 4, "st_opt"), optional(seq($._gval_sep, $._gopts_style))),
seq(key("ellipse", 3, "st_opt"), optional($.ellipse)),
seq(key("parallelaxis", -4, "st_opt"), optional(seq($._gval_sep, $._gopts_style))),
seq(key("spiderplot", 6, "st_opt"), optional(seq($._gval_sep, $._gopts_style))),
seq(alias("textbox", "st_opt"), optional(seq($._gval_sep, $._gopts_style))),
seq(key("watchpoint", 5, "st_opt"), optional(seq($._gval_sep, $._gopts_style))),
fillStyleOpt($),
),
),
),
),
ellipse: ($) =>
repeat1(
choice(
seq("units", alias(choice("xx", "xy", "yy"), "units_opt")),
seq("size", $.position, optional(seq(",", $.position))),
field("angle", seq("angle", $._expression)),
key("clip", undefined, "flag", 1),
),
),
table: ($) =>
prec.right(
seq(
key("table", 2, "opt"),
repeat(
choice(
choice($.string_literal, $.datablock),
"append",
dataSeparator($),
),
),
),
),
terminal: ($) =>
prec.right(
seq(
key("terminal", 1, "opt"),
optional(choice(
seq(alias(TERM_NAME, "name"), optional(seq($._gval_sep, $.t_opts))),
"push",
"pop",
)),
),
),
t_opts: ($) => $._gopts_style,
mono_color: ($) =>
choice(key("monochrome", 4), key("color", 3), key("colour", 3, "color")),
line_drawing_method: ($) => choice(key("rounded", -2, "mod"), alias("butt", "mod"), alias("square", "mod")),
background: ($) =>
choice(
seq(key("background", 5), field("color", choice($.colorspec, $._expression))),
key("nobackground", 7),
key("transparent", 5, "flag", 1), ),
tics: ($) => seq($._gval_sep, $.tics_opts),
title: ($) =>
prec.right(seq(key("title", 3, "opt"), optional(seq($._gval_sep, $._gopts_style)))),
vgrid: ($) => seq($.datablock, optional(seq("size", $._expression))),
view: ($) => seq($._gval_sep, choice($._view_angles, $._gopts)),
_view_angles: ($) =>
prec.dynamic(1, seq(optional($._expression), repeat1($._view_slot))),
_view_slot: ($) => prec.right(seq(",", optional($._expression))),
xdata: ($) =>
seq(key1("opt", K.axes, reg("data", 2)), optional(key("time", 1))),
xdtics: ($) => key1("opt", K.axes, "d", reg("tics", -1)),
xlabel: ($) =>
seq(
key1("opt", K.axes, reg("label", 3)),
optional(seq($._gval_sep, $._gopts_style)),
),
xmtics: ($) => key1("opt", K.axes, "m", reg("tics", -1)),
xrange: ($) =>
seq(
key1("opt", K.axes, reg("range", 3)),
repeat(
choice(
$.range_block,
key("reverse", 3, "flag", 1),
key("writeback", 3, "flag", 1),
key("extend", 3, "flag", 1),
"restore",
),
),
),
xtics: ($) =>
prec.left(
seq(
key1("opt", K.axes, reg("tics", 2)),
optional(seq($._gval_sep, $.tics_opts)),
),
),
xyplane: ($) =>
prec.right(seq(key("xyplane", 3, "opt"), optional(seq($._gval_sep, $._gopts)))),
zeroaxis: ($) =>
seq(key1("opt", K.zaxes, reg("zeroaxis", 5)), optional($.style_opts)),
cmd_show: ($) =>
seq(
key("show", 2, "cmd"),
choice(
$._argument_set_show,
$.multiplot,
key("colornames", 6, "opt"),
key("functions", 3, "opt"),
key("plot", 1, "opt"),
seq(
key("variables", 1, "opt"),
optional(seq($._gval_sep, choice(alias("all", "mod"), $.identifier))),
),
seq(key("version", 2, "opt"), optional(key("long", 1))),
),
),
cmd_splot: ($) =>
seq(alias($.cmd_splot_kw, "cmd"), optional("sample"), sep(",", $.plot_element)),
cmd_stats: ($) =>
seq(
alias("stats", "cmd"),
field("ranges", repeat($.range_block)),
field("filename", $._expression),
optional($.datafile_modifiers),
repeat(
choice(
seq(choice("name", "prefix"), field("name", $._expression)),
key("output", 3, "flag", 1),
),
),
),
cmd_system: ($) => seq(alias(choice("system", "!"), "cmd"), $._expression),
cmd_test: ($) =>
prec.left(
seq(alias("test", "cmd"), optional(choice("palette", alias("terminal", "mod")))),
),
cmd_undefine: ($) =>
seq(
key("undefine", 3, "cmd"),
repeat(token.immediate(UNDEFINE_ARG)),
),
cmd_unset: ($) =>
seq(
seq(key("unset", 3, "cmd"), optional($.for_block)),
$._argument_set_show,
),
cmd_vfill: ($) =>
seq(
alias(/vg?fill/, "cmd"),
optional("sample"),
sep(",", $.plot_element),
),
cmd_while: ($) =>
seq(
"while",
$.parenthesized_expression,
surround("{}", repeat($._statement)),
),
range_block: ($) => $._range_block,
_range_block: ($) =>
surround(
"[]",
optional(
seq(
optional(choice($.assignment, $._expression, "*")),
optional(
seq(
":",
optional(choice($._expression, "*")),
optional(seq(":", optional($._expression))),
),
),
),
),
),
for_block: ($) =>
prec.right(
repeat1(
seq(
"for",
surround(
"[]",
choice(
seq(field("start", $.identifier), "in", $._expression),
seq(
field("start", $.assignment),
":",
field("end", choice($._expression, "*")),
optional(seq(":", field("increment", $._expression))),
),
),
),
),
),
),
datafile_modifiers: ($) =>
repeat1(
choice(
$.binary_options,
$.matrix_options,
$._i_e_u_directives,
seq("skip", field("skip_lines", $._expression)),
alias(choice("convexhull", "concavehull"), $.hull),
seq("expand", field("increment", $._expression)),
field("smooth_data", $.smooth_options),
field("bins", $._bins),
key("columnheaders", -3),
key("rowheaders", -3),
"mask",
"sharpen",
"volatile",
"zsort",
"noautoscale",
),
),
binary_options: ($) =>
prec.left(
seq(
"binary",
choice(
repeat1(
choice(
seq(choice("record", "format"), "=", field("opt", $._expression)),
seq(
"rotate",
"=",
choice(
prec(1, seq(
field("opt", choice(
$.number,
$.parenthesized_expression,
alias(seq(alias(/[-+]/, $.operator), choice($.number, $.parenthesized_expression)), $.unary_expression),
)),
field("unit", choice(key("degrees", 1), alias($.unit_pi, "pi"))),
)),
field("opt", $._expression),
),
),
seq(alias(choice("dx", "dy", "dz", "skip"), "attr"), "=", field("opt", sep(":", $._expression))),
seq(alias("perpendicular", "attr"), "=", field("opt", $.parameter_list)),
seq("array", "=", field("opt", sep(":", choice($.parameter_list, $.number, alias(token(/\d+(x\d+)+/), $.number))))),
seq(choice("origin", "center"), "=", field("opt", sep(":", $.parameter_list))),
seq("filetype", "=", field("filetype", $.identifier)),
seq(alias("scan", "attr"), "=", field("scan", $.identifier)),
seq(key("endian", 3), "=", field("endian", choice("little", "big", "default", "swap", "swab", "middle", "pdp"))),
"flipx",
"flipy",
"flipz",
"transpose",
),
),
$.matrix_options,
),
),
),
matrix_options: ($) =>
choice(
"matrix",
seq("nonuniform", "matrix"),
seq(
"sparse",
"matrix",
"=",
surround(
"()",
field("cols", $._expression),
",",
field("rows", $._expression),
),
optional(
field(
"origin",
seq(
"origin",
"=",
surround("()", $._expression, ",", $._expression),
),
),
),
optional(seq("dx", "=", field("dx", $._expression))),
optional(seq("dy", "=", field("dy", $._expression))),
),
),
smooth_options: ($) =>
seq(
alias("smooth", "attr"),
repeat(
choice(
alias("unique", "mod"),
alias("frequency", "mod"),
alias("fnormal", "mod"),
alias("cumulative", "mod"),
alias("cnormal", "mod"),
key("csplines", 2, "mod"),
key("acsplines", 3, "mod"),
key("mcsplines", 3, "mod"),
alias("path", "mod"),
alias("bezier", "mod"),
alias("sbezier", "mod"),
seq(
alias("kdensity", "mod"),
optional(
seq(
alias(choice("bandwidth", "period"), "attr"),
field("bandwidth_period", $._expression),
),
),
),
alias("unwrap", "mod"),
),
),
),
_bins: ($) =>
prec.right(
repeat1(
choice(
seq(alias("bins", "attr"), optional(seq("=", $._expression))),
seq(alias("binrange", "attr"), $.range_block),
seq(alias("binwidth", "attr"), "=", $._expression),
seq(
alias("binvalue", "attr"),
optional(seq("=", choice(alias("sum", "mod"), alias("avg", "mod")))),
),
),
),
),
style_opts: ($) =>
prec.left(
repeat1(
choice(
$._sa,
seq(
$._lt,
field(
"lt",
choice($._expression, $.colorspec, "black", "bgnd", "background", alias("nodraw", "mod")),
),
),
$._sa,
$._linecolor,
seq($._dt, field("dt", $.dash_opts)),
seq($._pt, field("pt", choice("variable", $._expression))),
seq($._ps, field("ps", choice("variable", $._expression))),
$._sa,
$._sa,
$._sa,
seq($._fs, field("fs", $.fill_style)),
$._fillcolor,
key("nohidden3d", -2, "flag"),
alias("nocontours", "flag"),
key("nosurface", 6, "flag"),
key("palette", 3),
$.fontspec,
key("enhanced", 3, "flag", 1),
choice(alias(K.c, "cen"), alias(K.l, "lef"), alias(reg("right", 2), "rig")),
seq(key("rotate", 3, "flag", 1), optional(choice(seq(alias("by", "kw_fn"), $._expression), "variable"))),
offsetPos($),
$._textcolor,
),
),
),
arrow_opts: ($) =>
prec.left(
repeat1(
choice(
$.style_opts,
alias(/(no|back)?heads?/, "head"),
seq("size", $.position),
alias("fixed", "mod"),
choice("filled", "empty", "nofilled", alias("noborder", "flag")),
choice("front", "back"),
),
),
),
dash_opts: ($) =>
choice(
$._expression,
"solid",
surround(
"()",
sep(
",", seq(
field("solid", $._expression),
",",
field("empty", $._expression),
),
),
),
),
label_opts: ($) =>
prec.left(
repeat1(
choice(
prec.dynamic(1, field("label", $._expression)),
field("at", atPos($)),
choice(alias(K.c, "cen"), alias(K.l, "lef"), alias(K.r, "rig")),
seq(
key("rotate", 3, "flag", 1),
optional(
choice(
seq(alias("by", "kw_fn"), field("angle", $._expression)),
key("variable", 3),
),
),
),
$.fontspec,
key("enhanced", undefined, "flag", 1),
choice("front", "back"),
$._textcolor,
choice(seq("point", field("point", $.line_style)), alias("nopoint", "flag")),
field("offset", offsetPos($)),
seq(
key("boxed", -2, "flag", 1),
optional(field("boxstyle", seq(alias("bs", "arg"), $._expression))),
),
alias("hypertext", "flag"),
),
),
),
tics_opts: ($) => $._gopts_style,
line_style: ($) =>
prec.left(
seq(
optional(field("tag", $._expression)),
repeat1(
choice(
key("default", 3),
seq(
$._lt,
choice($._expression, $.colorspec, "black", "bgnd", "background", alias("nodraw", "mod")),
),
$._linecolor,
$._sa,
seq($._pt, $._expression),
seq($._ps, $._expression),
$._sa,
$._sa,
seq($._dt, $.dash_opts),
key("palette", 3),
),
),
),
),
fill_style: ($) =>
prec.left(
repeat1(
choice(
choice(
"empty",
seq(
optional(key("transparent", 5)),
key("solid", 1),
optional(field("density", $._expression)),
),
seq(
optional(key("transparent", 5)),
key("pattern", 3),
optional(field("n", $._expression)),
),
),
seq(
key("border", 2, "flag", 1),
optional(seq(optional($._lt), $._expression)),
optional($._linecolor),
),
),
),
),
fontspec: ($) => seq(alias("font", "arg"), field("font", $._expression)),
_linecolor: ($) =>
seq($._lc, field("lc", choice($._expression, $.colorspec))),
_textcolor: ($) =>
seq(
$._tc,
field(
"tc",
choice(
$.colorspec,
seq($._lt, $._expression),
$._sa,
"default",
$._expression,
"variable",
),
),
),
_fillcolor: ($) =>
seq(
$._fc,
field(
"fc",
choice(
$.colorspec,
seq($._lt, $._expression),
$._sa,
$._expression,
),
),
),
colorspec: ($) =>
prec.left(
1,
choice(
seq(key("rgbcolor", 3), choice($._expression, "variable")),
seq(
key("palette", 3),
optional(
choice(
seq("frac", field("val", $._expression)),
seq(alias("cb", "axis"), field("val", $._expression)),
alias("z", "axis"),
),
),
),
key("variable", 3),
"bgnd",
"black",
"background",
),
),
_i_e_u_directives: ($) => choice($.index, $.every, $.using),
index: ($) =>
prec.left(
seq(
key("index", 1, "attr"),
seq(
field("start_name", $._expression),
optional(
seq(
":",
field("end", $._expression),
optional(seq(":", field("step", $._expression))),
),
),
),
),
),
every: ($) =>
prec.left(
seq(
alias("every", "attr"),
optional(
seq(
optional(field("point_incr", $._expression)),
optional(
seq(
":",
optional(field("block_incr", $._expression)),
optional(
seq(
":",
optional(field("start_point", $._expression)),
optional(
seq(
":",
optional(field("start_block", $._expression)),
optional(
seq(
":",
optional(field("end_point", $._expression)),
optional(
seq(
":",
optional(field("end_block", $._expression)),
),
),
),
),
),
),
),
),
),
),
),
),
),
),
using: ($) =>
field(
"using",
prec.right(seq(
key("using", 1, "attr"),
sep(":", choice(
surround("()", sep(",", choice($.assignment, $._expression))),
$._expression,
)),
optional(field("format", $.string_literal)),
)),
),
position: ($) =>
prec.left(
seq(
optional($.system),
field("x", $._expression),
optional(
seq(
",",
optional($.system),
field("y", $._expression),
optional(seq(",", optional($.system), field("z", $._expression))),
),
),
),
),
system: (_) =>
choice(
key("first", 3, "coord"),
key("second", 3, "coord"),
key("graph", 2, "coord"),
key("screen", 2, "coord"),
key("character", 4, "coord"),
alias("polar", "coord"), ),
_expression: ($) =>
prec.left(
choice(
$.identifier,
$.function,
$.array,
$.subscript,
$.datablock,
$.number,
$.complex,
$.string_literal,
$.sum_block,
$.parenthesized_expression,
$.unary_expression,
$.binary_expression,
$.ternary_expression,
),
),
_tag_atom: ($) =>
choice(
$.number,
$.unary_expression,
$.identifier,
),
number: (_) => {
const hex_literal = seq(choice("0x", "0X"), /[\da-fA-F](_?[\da-fA-F])*/);
const octal_literal = seq(choice("0o", "0O"), /[0-7](_?[0-7])*/);
const decimal_digits = /\d(_?\d)*/;
const signed_integer = seq(optional(choice("-", "+")), decimal_digits);
const exponent_part = seq(choice("e", "E"), signed_integer);
const decimal_integer_literal = choice(
"0",
seq(
optional("0"),
/[1-9]/,
optional(seq(optional("_"), decimal_digits)),
),
);
const decimal_literal = choice(
seq(
decimal_integer_literal,
".",
optional(decimal_digits),
optional(exponent_part),
),
seq(".", decimal_digits, optional(exponent_part)),
seq(decimal_integer_literal, exponent_part),
decimal_digits,
);
const unit = choice("cm", "in", "inch", "mm", "pt", "pc", "bp", "dd", "cc", "pi");
return token(
seq(choice(decimal_literal, hex_literal, octal_literal), optional(unit)),
);
},
complex: ($) =>
surround(
"{}",
field("Re", $._expression),
",",
field("Im", $._expression),
),
string_literal: ($) =>
choice(
seq(
'"',
repeat(
choice(
token.immediate(prec(1, /[^"\\%\n]+/)),
$.escape_sequence,
$.format_specifier,
token.immediate(prec(0, /%/)), ),
),
token.immediate('"'),
),
seq(
"'",
repeat(
choice(
token.immediate(prec(1, /[^'%\n]+/)),
$.format_specifier,
token.immediate(prec(0, /%/)), ),
),
token.immediate("'"),
),
),
escape_sequence: (_) =>
token.immediate(
/\\(?:[ \t]*\n|[\\'"nrtab]|\d{3}|x[0-9a-fA-F]{2}|[uU][0-9a-fA-F]{4,8}|.)/
),
format_specifier: (_) =>
token.immediate(
/%%|%[-+0 #*]*\d*(?:\.\d+)?(?:\[[^\]]*\]|uchar|int|float|(?:hh|ll|[hlLjztq])?[a-zA-Z])/
),
sum_block: ($) =>
prec.left(
seq(
alias("sum", "kw_fn"),
surround("[]", $.identifier, "=", $._expression, ":", $._expression),
$._expression,
),
),
parenthesized_expression: ($) =>
prec(PREC.PAREN, surround("()", $._expression)),
unary_expression: ($) =>
choice(
...[
[/[-+]/, PREC.UNARY],
["~", PREC.BIT_NOT],
["!", PREC.UNARY],
].map(([operator, precedence]) =>
prec.left(
precedence,
seq(alias(operator, $.operator), $._expression),
),
),
prec.left(PREC.POWER, seq($._expression, alias("!", $.operator))),
prec.left(
PREC.UNARY,
seq(alias("$", $.operator), choice($.number, token.immediate("#"))),
),
prec.left(PREC.UNARY, surround(alias("|", $.operator), $._expression)),
),
binary_expression: ($) =>
choice(
...[
["**", PREC.POWER],
["*", PREC.TIMES],
[/[\/%]/, PREC.TIMES],
[/[-+]/, PREC.PLUS],
[/==|!=|<=|>=|<|>/, PREC.COMPARE],
[">>", PREC.SHIFT],
["<<", PREC.SHIFT],
["&", PREC.BIT_AND],
["^", PREC.BIT_OR],
["|", PREC.BIT_OR],
["&&", PREC.AND],
["||", PREC.OR],
[".", PREC.CONCAT],
].map(([operator, precedence]) =>
prec.left(
precedence,
seq($._expression, alias(operator, $.operator), $._expression),
),
),
...[
[/eq|ne/, PREC.COMPARE],
].map(([operator, precedence]) =>
prec.left(
precedence,
seq($._expression, alias(operator, $.keyword_op), $._expression),
),
),
),
ternary_expression: ($) =>
prec.left(
PREC.TERNARY,
seq(
field("condition", choice($.assignment, $._expression)),
alias("?", $.ternary_op),
field("true", choice($.assignment, $._expression)),
alias(":", $.ternary_op),
field("false", choice($.assignment, $._expression)),
),
),
identifier: (_) => token(IDENTIFIER),
array: ($) =>
prec(
1,
seq(
field("name", $.identifier),
surround("[]", $._expression),
),
),
subscript: ($) =>
prec(
2,
seq(
choice($.identifier, $.string_literal),
"[",
optional(choice($._expression, "*")),
":",
optional(choice($._expression, "*")),
"]",
),
),
datablock: (_) => token(seq("$", IDENTIFIER)),
function: ($) =>
prec(
1,
seq(field("name", $.identifier), field("parameters", $.parameter_list)),
),
parameter_list: ($) => surround("()", sep(",", $._expression)),
comment: ($) => seq("#", alias(token(/.*(\\\s*\n.*)*/), $.comment_content)),
},
});
function sep(separator, rule, rep = 0, assoc = "") {
const repeatedRule =
rep === 0 ? repeat(seq(separator, rule)) : repeat1(seq(separator, rule));
const associatedRule =
assoc === "l"
? prec.left(repeatedRule)
: assoc === "r"
? prec.right(repeatedRule)
: repeatedRule;
return seq(rule, associatedRule);
}
function surround(bracket, ...rules) {
const brackets = {
"()": ["(", ")"],
"[]": ["[", "]"],
"{}": ["{", "}"],
};
const [open, close] = brackets[bracket] || [bracket, bracket];
return seq(open, ...rules, close);
}
function key1(aka, ...reg) {
const regStr = reg.map((reg) => (reg instanceof RegExp ? reg.source : reg));
return alias(new RegExp(regStr.join("")), aka);
}
function key(word, minChar = word.length, aka = word, opt = 0) {
return alias(reg(word, minChar, opt), aka);
}
function reg(word, minChar = word.length, opt = 0) {
const regexPattern =
word.slice(0, minChar) +
word
.slice(minChar)
.split("")
.map((char) => `(${char}`)
.join("") +
")?".repeat(word.slice(minChar).length);
return opt === 0
? new RegExp(regexPattern)
: opt === 1
? new RegExp(`(no)?${regexPattern}`)
: new RegExp(`${regexPattern}|${opt}`);
}