aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--lexers/LexLPeg.cxx1395
1 files changed, 701 insertions, 694 deletions
diff --git a/lexers/LexLPeg.cxx b/lexers/LexLPeg.cxx
index e79a7f83d..5f4b95b01 100644
--- a/lexers/LexLPeg.cxx
+++ b/lexers/LexLPeg.cxx
@@ -36,12 +36,12 @@ using namespace Scintilla;
#if LUA_VERSION_NUM < 502
#define luaL_requiref(l, s, f, _) \
- (lua_pushcfunction(l, f), lua_pushstring(l, s), lua_call(l, 1, 1))
+ (lua_pushcfunction(l, f), lua_pushstring(l, s), lua_call(l, 1, 1))
#define lua_rawlen lua_objlen
#define LUA_OK 0
#define lua_rawgetp(l, i, p) (lua_pushlightuserdata(l, p), lua_rawget(l, i))
#define lua_rawsetp(l, i, p) \
- (lua_pushlightuserdata(l, p), lua_insert(l, -2), lua_rawset(l, i))
+ (lua_pushlightuserdata(l, p), lua_insert(l, -2), lua_rawset(l, i))
#endif
#if LUA_VERSION_NUM < 503
#define lua_getfield(l, i, k) (lua_getfield(l, i, k), lua_type(l, -1))
@@ -50,109 +50,107 @@ using namespace Scintilla;
/** lexer.property[key] metamethod. */
static int lexer_property_index(lua_State *L) {
- const char *property = lua_tostring(L, lua_upvalueindex(1));
- lua_getfield(L, LUA_REGISTRYINDEX, "sci_lexer_lpeg");
- lua_rawgetp(L, LUA_REGISTRYINDEX, lua_touserdata(L, -1));
- lua_getfield(L, -1, "_PROPS");
- auto props = static_cast<PropSetSimple *>(lua_touserdata(L, -1));
- lua_getfield(L, -2, "_BUFFER");
- auto buffer = static_cast<IDocument *>(lua_touserdata(L, -1));
- if (strcmp(property, "fold_level") == 0) {
- luaL_argcheck(L, buffer, 1, "must be lexing or folding");
- lua_pushinteger(L, buffer->GetLevel(luaL_checkinteger(L, 2)));
- } else if (strcmp(property, "indent_amount") == 0) {
- luaL_argcheck(L, buffer, 1, "must be lexing or folding");
- lua_pushinteger(L, buffer->GetLineIndentation(luaL_checkinteger(L, 2)));
- } else if (strcmp(property, "property") == 0) {
- lua_pushstring(L, props->Get(luaL_checkstring(L, 2)));
- } else if (strcmp(property, "property_int") == 0) {
- lua_pushstring(L, props->Get(luaL_checkstring(L, 2)));
- lua_pushinteger(L, lua_tointeger(L, -1));
- } else if (strcmp(property, "style_at") == 0) {
- luaL_argcheck(L, buffer, 1, "must be lexing or folding");
- int style = buffer->StyleAt(luaL_checkinteger(L, 2) - 1);
- lua_getfield(L, 4, "_TOKENSTYLES");
- lua_pushnil(L);
- while (lua_next(L, -2)) {
- if (luaL_checkinteger(L, -1) == style) break;
- lua_pop(L, 1); // value
- }
- lua_pop(L, 1); // style_num, leaving name on top
- } else if (strcmp(property, "line_state") == 0) {
- luaL_argcheck(L, buffer, 1, "must be lexing or folding");
- lua_pushinteger(L, buffer->GetLineState(luaL_checkinteger(L, 2)));
- }
- return 1;
+ const char *property = lua_tostring(L, lua_upvalueindex(1));
+ lua_getfield(L, LUA_REGISTRYINDEX, "sci_lexer_lpeg");
+ lua_rawgetp(L, LUA_REGISTRYINDEX, lua_touserdata(L, -1));
+ lua_getfield(L, -1, "_PROPS");
+ auto props = static_cast<PropSetSimple *>(lua_touserdata(L, -1));
+ lua_getfield(L, -2, "_BUFFER");
+ auto buffer = static_cast<IDocument *>(lua_touserdata(L, -1));
+ if (strcmp(property, "fold_level") == 0) {
+ luaL_argcheck(L, buffer, 1, "must be lexing or folding");
+ lua_pushinteger(L, buffer->GetLevel(luaL_checkinteger(L, 2)));
+ } else if (strcmp(property, "indent_amount") == 0) {
+ luaL_argcheck(L, buffer, 1, "must be lexing or folding");
+ lua_pushinteger(L, buffer->GetLineIndentation(luaL_checkinteger(L, 2)));
+ } else if (strcmp(property, "property") == 0) {
+ lua_pushstring(L, props->Get(luaL_checkstring(L, 2)));
+ } else if (strcmp(property, "property_int") == 0) {
+ lua_pushstring(L, props->Get(luaL_checkstring(L, 2)));
+ lua_pushinteger(L, lua_tointeger(L, -1));
+ } else if (strcmp(property, "style_at") == 0) {
+ luaL_argcheck(L, buffer, 1, "must be lexing or folding");
+ int style = buffer->StyleAt(luaL_checkinteger(L, 2) - 1);
+ lua_getfield(L, 4, "_TOKENSTYLES");
+ lua_pushnil(L);
+ while (lua_next(L, -2)) {
+ if (luaL_checkinteger(L, -1) == style) break;
+ lua_pop(L, 1); // value
+ }
+ lua_pop(L, 1); // style_num, leaving name on top
+ } else if (strcmp(property, "line_state") == 0) {
+ luaL_argcheck(L, buffer, 1, "must be lexing or folding");
+ lua_pushinteger(L, buffer->GetLineState(luaL_checkinteger(L, 2)));
+ }
+ return 1;
}
/** lexer.property[key] = value metamethod. */
static int lexer_property_newindex(lua_State *L) {
- const char *property = lua_tostring(L, lua_upvalueindex(1));
- luaL_argcheck(L, strcmp(property, "fold_level") != 0 &&
- strcmp(property, "indent_amount") != 0 &&
- strcmp(property, "property_int") != 0 &&
- strcmp(property, "style_at") != 0 &&
- strcmp(property, "line_from_position") != 0, 3,
- "read-only property");
- lua_getfield(L, LUA_REGISTRYINDEX, "sci_lexer_lpeg");
- lua_rawgetp(L, LUA_REGISTRYINDEX, lua_touserdata(L, -1));
- if (strcmp(property, "property") == 0) {
- lua_getfield(L, -1, "_PROPS");
- auto props = static_cast<PropSetSimple *>(lua_touserdata(L, -1));
- props->Set(luaL_checkstring(L, 2), luaL_checkstring(L, 3), lua_rawlen(L, 2),
- lua_rawlen(L, 3));
- } else if (strcmp(property, "line_state") == 0) {
- luaL_argcheck(L, lua_getfield(L, -1, "_BUFFER"), 1,
- "must be lexing or folding");
- auto buffer = static_cast<IDocument *>(lua_touserdata(L, -1));
- buffer->SetLineState(luaL_checkinteger(L, 2), luaL_checkinteger(L, 3));
- }
- return 0;
+ const char *property = lua_tostring(L, lua_upvalueindex(1));
+ luaL_argcheck(
+ L, strcmp(property, "fold_level") != 0 &&
+ strcmp(property, "indent_amount") != 0 &&
+ strcmp(property, "property_int") != 0 &&
+ strcmp(property, "style_at") != 0 &&
+ strcmp(property, "line_from_position") != 0, 3, "read-only property");
+ lua_getfield(L, LUA_REGISTRYINDEX, "sci_lexer_lpeg");
+ lua_rawgetp(L, LUA_REGISTRYINDEX, lua_touserdata(L, -1));
+ if (strcmp(property, "property") == 0) {
+ lua_getfield(L, -1, "_PROPS");
+ auto props = static_cast<PropSetSimple *>(lua_touserdata(L, -1));
+ props->Set(
+ luaL_checkstring(L, 2), luaL_checkstring(L, 3), lua_rawlen(L, 2),
+ lua_rawlen(L, 3));
+ } else if (strcmp(property, "line_state") == 0) {
+ luaL_argcheck(
+ L, lua_getfield(L, -1, "_BUFFER"), 1, "must be lexing or folding");
+ auto buffer = static_cast<IDocument *>(lua_touserdata(L, -1));
+ buffer->SetLineState(luaL_checkinteger(L, 2), luaL_checkinteger(L, 3));
+ }
+ return 0;
}
/** The lexer's `line_from_position` Lua function. */
static int line_from_position(lua_State *L) {
- auto buffer = static_cast<IDocument *>(lua_touserdata(L,
- lua_upvalueindex(1)));
- lua_pushinteger(L, buffer->LineFromPosition(luaL_checkinteger(L, 1) - 1));
- return 1;
+ auto buffer = static_cast<IDocument *>(
+ lua_touserdata(L, lua_upvalueindex(1)));
+ lua_pushinteger(L, buffer->LineFromPosition(luaL_checkinteger(L, 1) - 1));
+ return 1;
}
/** lexer.property metamethod. */
static int lexer_index(lua_State *L) {
- const char *key = lua_tostring(L, 2);
- if (strcmp(key, "fold_level") == 0 || strcmp(key, "indent_amount") == 0 ||
- strcmp(key, "property") == 0 || strcmp(key, "property_int") == 0 ||
- strcmp(key, "style_at") == 0 || strcmp(key, "line_state") == 0) {
- lua_createtable(L, 0, 0);
- lua_createtable(L, 0, 2);
- lua_pushvalue(L, 2), lua_pushcclosure(L, lexer_property_index, 1);
- lua_setfield(L, -2, "__index");
- lua_pushvalue(L, 2), lua_pushcclosure(L, lexer_property_newindex, 1);
- lua_setfield(L, -2, "__newindex");
- lua_setmetatable(L, -2);
- } else if (strcmp(key, "line_from_position") == 0) {
- lua_getfield(L, LUA_REGISTRYINDEX, "sci_lexer_lpeg");
- lua_rawgetp(L, LUA_REGISTRYINDEX, lua_touserdata(L, -1));
- luaL_argcheck(L, lua_getfield(L, -1, "_BUFFER"), 2,
- "must be lexing or folding");
- lua_pushcclosure(L, line_from_position, 1);
- } else lua_rawget(L, 1);
- return 1;
+ const char *key = lua_tostring(L, 2);
+ if (strcmp(key, "fold_level") == 0 || strcmp(key, "indent_amount") == 0 ||
+ strcmp(key, "property") == 0 || strcmp(key, "property_int") == 0 ||
+ strcmp(key, "style_at") == 0 || strcmp(key, "line_state") == 0) {
+ lua_createtable(L, 0, 0);
+ lua_createtable(L, 0, 2);
+ lua_pushvalue(L, 2), lua_pushcclosure(L, lexer_property_index, 1);
+ lua_setfield(L, -2, "__index");
+ lua_pushvalue(L, 2), lua_pushcclosure(L, lexer_property_newindex, 1);
+ lua_setfield(L, -2, "__newindex");
+ lua_setmetatable(L, -2);
+ } else if (strcmp(key, "line_from_position") == 0) {
+ lua_getfield(L, LUA_REGISTRYINDEX, "sci_lexer_lpeg");
+ lua_rawgetp(L, LUA_REGISTRYINDEX, lua_touserdata(L, -1));
+ luaL_argcheck(
+ L, lua_getfield(L, -1, "_BUFFER"), 2, "must be lexing or folding");
+ lua_pushcclosure(L, line_from_position, 1);
+ } else lua_rawget(L, 1);
+ return 1;
}
/** lexer.property = value metamethod. */
static int lexer_newindex(lua_State *L) {
- const char *key = lua_tostring(L, 2);
- luaL_argcheck(L, strcmp(key, "fold_level") != 0 &&
- strcmp(key, "indent_amount") != 0 &&
- strcmp(key, "property") != 0 &&
- strcmp(key, "property_int") != 0 &&
- strcmp(key, "style_at") != 0 &&
- strcmp(key, "line_state") != 0 &&
- strcmp(key, "line_from_position") != 0, 3,
- "read-only property");
- return (lua_rawset(L, 1), 0);
+ const char *key = lua_tostring(L, 2);
+ luaL_argcheck(
+ L, strcmp(key, "fold_level") != 0 && strcmp(key, "indent_amount") != 0 &&
+ strcmp(key, "property") != 0 && strcmp(key, "property_int") != 0 &&
+ strcmp(key, "style_at") != 0 && strcmp(key, "line_state") != 0 &&
+ strcmp(key, "line_from_position") != 0, 3, "read-only property");
+ return (lua_rawset(L, 1), 0);
}
/**
@@ -162,635 +160,644 @@ static int lexer_newindex(lua_State *L) {
* @param L The Lua State.
*/
static void expand_property(lua_State *L) {
- //int orig_stack_top = lua_gettop(L);
- lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"), lua_getfield(L, -1, "lexer");
- lua_getfield(L, -1, "property_expanded");
- lua_pushvalue(L, -4), lua_gettable(L, -2), lua_replace(L, -5);
- lua_pop(L, 3); // property_expanded, lexer, _LOADED
- //assert(lua_gettop(L) == orig_stack_top);
+ //int orig_stack_top = lua_gettop(L);
+ lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"), lua_getfield(L, -1, "lexer");
+ lua_getfield(L, -1, "property_expanded");
+ lua_pushvalue(L, -4), lua_gettable(L, -2), lua_replace(L, -5);
+ lua_pop(L, 3); // property_expanded, lexer, _LOADED
+ //assert(lua_gettop(L) == orig_stack_top);
}
/** The LPeg Scintilla lexer. */
class LexerLPeg : public ILexer {
- /**
- * The lexer's Lua state.
- * It is cleared each time the lexer language changes unless `own_lua` is
- * `true`.
- */
- lua_State *L;
- /**
- * The flag indicating whether or not the Lua State is owned by the lexer.
- */
- bool own_lua = true;
- /**
- * The set of properties for the lexer.
- * The `lexer.name`, `lexer.lpeg.home`, and `lexer.lpeg.color.theme`
- * properties must be defined before running the lexer.
- */
- PropSetSimple props;
- /** The function to send Scintilla messages with. */
- SciFnDirect SS = nullptr;
- /** The Scintilla object the lexer belongs to. */
- sptr_t sci = 0;
- /**
- * The flag indicating whether or not the lexer needs to be re-initialized.
- * Re-initialization is required after the lexer language changes.
- */
- bool reinit = true;
- /**
- * The flag indicating whether or not the lexer language has embedded lexers.
- */
- bool multilang = false;
- /**
- * The list of style numbers considered to be whitespace styles.
- * This is used in multi-language lexers when backtracking to whitespace to
- * determine which lexer grammar to use.
- */
- bool ws[STYLE_MAX + 1];
-
- /**
- * Logs the given error message or a Lua error message, prints it, and clears
- * the stack.
- * Error messages are logged to the "lexer.lpeg.error" property.
- * @param L The Lua State.
- * @param str The error message to log and print. If `nullptr`, logs and
- * prints the Lua error message at the top of the stack.
- */
- void log_error(lua_State *L, const char *str = nullptr) {
- const char *key = "lexer.lpeg.error";
- const char *value = str ? str : lua_tostring(L, -1);
- props.Set(key, value, strlen(key), strlen(value));
- fprintf(stderr, "Lua Error: %s.\n", value);
- lua_settop(L, 0);
- }
-
- /**
- * Parses the given style string to set the properties for the given style
- * number.
- * @param num The style number to set properties for.
- * @param style The style string containing properties to set.
- */
- void SetStyle(int num, const char *style) {
- auto style_copy = static_cast<char *>(malloc(strlen(style) + 1));
- char *key = strcpy(style_copy, style), *next = nullptr, *val = nullptr;
- while (key) {
- if ((next = strchr(key, ','))) *next++ = '\0';
- if ((val = strchr(key, ':'))) *val++ = '\0';
- if (strcmp(key, "font") == 0 && val)
- SS(sci, SCI_STYLESETFONT, num, reinterpret_cast<sptr_t>(val));
- else if (strcmp(key, "size") == 0 && val)
- SS(sci, SCI_STYLESETSIZE, num, static_cast<int>(atoi(val)));
- else if (strcmp(key, "bold") == 0 || strcmp(key, "notbold") == 0 ||
- strcmp(key, "weight") == 0) {
+ /**
+ * The lexer's Lua state.
+ * It is cleared each time the lexer language changes unless `own_lua` is
+ * `true`.
+ */
+ lua_State *L;
+ /**
+ * The flag indicating whether or not the Lua State is owned by the lexer.
+ */
+ bool own_lua = true;
+ /**
+ * The set of properties for the lexer.
+ * The `lexer.name`, `lexer.lpeg.home`, and `lexer.lpeg.color.theme`
+ * properties must be defined before running the lexer.
+ */
+ PropSetSimple props;
+ /** The function to send Scintilla messages with. */
+ SciFnDirect SS = nullptr;
+ /** The Scintilla object the lexer belongs to. */
+ sptr_t sci = 0;
+ /**
+ * The flag indicating whether or not the lexer needs to be re-initialized.
+ * Re-initialization is required after the lexer language changes.
+ */
+ bool reinit = true;
+ /**
+ * The flag indicating whether or not the lexer language has embedded lexers.
+ */
+ bool multilang = false;
+ /**
+ * The list of style numbers considered to be whitespace styles.
+ * This is used in multi-language lexers when backtracking to whitespace to
+ * determine which lexer grammar to use.
+ */
+ bool ws[STYLE_MAX + 1];
+
+ /**
+ * Logs the given error message or a Lua error message, prints it, and clears
+ * the stack.
+ * Error messages are logged to the "lexer.lpeg.error" property.
+ * @param L The Lua State.
+ * @param str The error message to log and print. If `nullptr`, logs and
+ * prints the Lua error message at the top of the stack.
+ */
+ void log_error(lua_State *L, const char *str = nullptr) {
+ const char *key = "lexer.lpeg.error";
+ const char *value = str ? str : lua_tostring(L, -1);
+ props.Set(key, value, strlen(key), strlen(value));
+ fprintf(stderr, "Lua Error: %s.\n", value);
+ lua_settop(L, 0);
+ }
+
+ /**
+ * Parses the given style string to set the properties for the given style
+ * number.
+ * @param num The style number to set properties for.
+ * @param style The style string containing properties to set.
+ */
+ void SetStyle(int num, const char *style) {
+ auto style_copy = static_cast<char *>(malloc(strlen(style) + 1));
+ char *key = strcpy(style_copy, style), *next = nullptr, *val = nullptr;
+ while (key) {
+ if ((next = strchr(key, ','))) *next++ = '\0';
+ if ((val = strchr(key, ':'))) *val++ = '\0';
+ if (strcmp(key, "font") == 0 && val)
+ SS(sci, SCI_STYLESETFONT, num, reinterpret_cast<sptr_t>(val));
+ else if (strcmp(key, "size") == 0 && val)
+ SS(sci, SCI_STYLESETSIZE, num, static_cast<int>(atoi(val)));
+ else if (strcmp(key, "bold") == 0 || strcmp(key, "notbold") == 0 ||
+ strcmp(key, "weight") == 0) {
#if !CURSES
- int weight = SC_WEIGHT_NORMAL;
- if (*key == 'b')
- weight = SC_WEIGHT_BOLD;
- else if (*key == 'w' && val)
- weight = atoi(val);
- SS(sci, SCI_STYLESETWEIGHT, num, weight);
+ int weight = SC_WEIGHT_NORMAL;
+ if (*key == 'b')
+ weight = SC_WEIGHT_BOLD;
+ else if (*key == 'w' && val)
+ weight = atoi(val);
+ SS(sci, SCI_STYLESETWEIGHT, num, weight);
#else
- // Scintilla curses requires font attributes to be stored in the "font
- // weight" style attribute.
- // First, clear any existing SC_WEIGHT_NORMAL, SC_WEIGHT_SEMIBOLD, or
- // SC_WEIGHT_BOLD values stored in the lower 16 bits. Then set the
- // appropriate curses attr.
- sptr_t weight = SS(sci, SCI_STYLEGETWEIGHT, num, 0) & ~(A_COLOR |
- A_CHARTEXT);
- int bold = *key == 'b' ||
- (*key == 'w' && val && atoi(val) > SC_WEIGHT_NORMAL);
- SS(sci, SCI_STYLESETWEIGHT, num,
- bold ? weight | A_BOLD : weight & ~A_BOLD);
+ // Scintilla curses requires font attributes to be stored in the "font
+ // weight" style attribute.
+ // First, clear any existing SC_WEIGHT_NORMAL, SC_WEIGHT_SEMIBOLD, or
+ // SC_WEIGHT_BOLD values stored in the lower 16 bits. Then set the
+ // appropriate curses attr.
+ sptr_t weight =
+ SS(sci, SCI_STYLEGETWEIGHT, num, 0) & ~(A_COLOR | A_CHARTEXT);
+ int bold =
+ *key == 'b' || (*key == 'w' && val && atoi(val) > SC_WEIGHT_NORMAL);
+ SS(
+ sci, SCI_STYLESETWEIGHT, num,
+ bold ? weight | A_BOLD : weight & ~A_BOLD);
#endif
- } else if (strcmp(key, "italics") == 0 || strcmp(key, "notitalics") == 0)
- SS(sci, SCI_STYLESETITALIC, num, *key == 'i');
- else if (strcmp(key, "underlined") == 0 ||
- strcmp(key, "notunderlined") == 0) {
+ } else if (strcmp(key, "italics") == 0 || strcmp(key, "notitalics") == 0)
+ SS(sci, SCI_STYLESETITALIC, num, *key == 'i');
+ else if (strcmp(key, "underlined") == 0 ||
+ strcmp(key, "notunderlined") == 0) {
#if !CURSES
- SS(sci, SCI_STYLESETUNDERLINE, num, *key == 'u');
+ SS(sci, SCI_STYLESETUNDERLINE, num, *key == 'u');
#else
- // Scintilla curses requires font attributes to be stored in the "font
- // weight" style attribute.
- // First, clear any existing SC_WEIGHT_NORMAL, SC_WEIGHT_SEMIBOLD, or
- // SC_WEIGHT_BOLD values stored in the lower 16 bits. Then set the
- // appropriate curses attr.
- sptr_t weight = SS(sci, SCI_STYLEGETWEIGHT, num, 0) & ~(A_COLOR |
- A_CHARTEXT);
- SS(sci, SCI_STYLESETWEIGHT, num,
- (*key == 'u') ? weight | A_UNDERLINE : weight & ~A_UNDERLINE);
+ // Scintilla curses requires font attributes to be stored in the "font
+ // weight" style attribute.
+ // First, clear any existing SC_WEIGHT_NORMAL, SC_WEIGHT_SEMIBOLD, or
+ // SC_WEIGHT_BOLD values stored in the lower 16 bits. Then set the
+ // appropriate curses attr.
+ sptr_t weight =
+ SS(sci, SCI_STYLEGETWEIGHT, num, 0) & ~(A_COLOR | A_CHARTEXT);
+ SS(
+ sci, SCI_STYLESETWEIGHT, num,
+ (*key == 'u') ? weight | A_UNDERLINE : weight & ~A_UNDERLINE);
#endif
- } else if ((strcmp(key, "fore") == 0 || strcmp(key, "back") == 0) &&
- val) {
- int msg = (*key == 'f') ? SCI_STYLESETFORE : SCI_STYLESETBACK;
- int color = static_cast<int>(strtol(val, nullptr, 0));
- if (*val == '#') { // #RRGGBB format; Scintilla format is 0xBBGGRR
- color = static_cast<int>(strtol(val + 1, nullptr, 16));
- color = ((color & 0xFF0000) >> 16) | (color & 0xFF00) |
- ((color & 0xFF) << 16); // convert to 0xBBGGRR
- }
- SS(sci, msg, num, color);
- } else if (strcmp(key, "eolfilled") == 0 ||
- strcmp(key, "noteolfilled") == 0)
- SS(sci, SCI_STYLESETEOLFILLED, num, *key == 'e');
- else if (strcmp(key, "characterset") == 0 && val)
- SS(sci, SCI_STYLESETCHARACTERSET, num, static_cast<int>(atoi(val)));
- else if (strcmp(key, "case") == 0 && val) {
- if (*val == 'u')
- SS(sci, SCI_STYLESETCASE, num, SC_CASE_UPPER);
- else if (*val == 'l')
- SS(sci, SCI_STYLESETCASE, num, SC_CASE_LOWER);
- } else if (strcmp(key, "visible") == 0 || strcmp(key, "notvisible") == 0)
- SS(sci, SCI_STYLESETVISIBLE, num, *key == 'v');
- else if (strcmp(key, "changeable") == 0 ||
- strcmp(key, "notchangeable") == 0)
- SS(sci, SCI_STYLESETCHANGEABLE, num, *key == 'c');
- else if (strcmp(key, "hotspot") == 0 || strcmp(key, "nothotspot") == 0)
- SS(sci, SCI_STYLESETHOTSPOT, num, *key == 'h');
- key = next;
- }
- free(style_copy);
- }
-
- /**
- * Iterates through the lexer's `_TOKENSTYLES`, setting the style properties
- * for all defined styles.
- */
- bool SetStyles() {
- //int orig_stack_top = lua_gettop(L);
- // If the lexer defines additional styles, set their properties first (if
- // the user has not already defined them).
- lua_rawgetp(L, LUA_REGISTRYINDEX, reinterpret_cast<void *>(this));
- lua_getfield(L, -1, "_EXTRASTYLES");
- lua_pushnil(L);
- while (lua_next(L, -2)) {
- if (lua_isstring(L, -2) && lua_isstring(L, -1)) {
- lua_pushstring(L, "style."), lua_pushvalue(L, -3), lua_concat(L, 2);
- if (!*props.Get(lua_tostring(L, -1)))
- props.Set(lua_tostring(L, -1), lua_tostring(L, -2), lua_rawlen(L, -1),
- lua_rawlen(L, -2));
- lua_pop(L, 1); // style name
- }
- lua_pop(L, 1); // value
- }
- lua_pop(L, 1); // _EXTRASTYLES
-
- if (!SS || !sci) {
- lua_pop(L, 1); // lexer object
- // Skip, but do not report an error since `reinit` would remain `false`
- // and subsequent calls to `Lex()` and `Fold()` would repeatedly call this
- // function and error.
- //assert(lua_gettop(L) == orig_stack_top);
- return true;
- }
- lua_pushstring(L, "style.default"), expand_property(L);
- SetStyle(STYLE_DEFAULT, lua_tostring(L, -1));
- lua_pop(L, 1); // style
- SS(sci, SCI_STYLECLEARALL, 0, 0); // set default styles
- lua_getfield(L, -1, "_TOKENSTYLES");
- lua_pushnil(L);
- while (lua_next(L, -2)) {
- if (lua_isstring(L, -2) && lua_isnumber(L, -1) &&
- lua_tointeger(L, -1) != STYLE_DEFAULT) {
- lua_pushstring(L, "style."), lua_pushvalue(L, -3), lua_concat(L, 2);
- expand_property(L);
- SetStyle(lua_tointeger(L, -2), lua_tostring(L, -1));
- lua_pop(L, 1); // style
- }
- lua_pop(L, 1); // value
- }
- lua_pop(L, 2); // _TOKENSTYLES, lexer object
- //assert(lua_gettop(L) == orig_stack_top);
- return true;
- }
-
- /**
- * Returns the style name for the given style number.
- * @param style The style number to get the style name for.
- * @return style name or nullptr
- */
- const char *GetStyleName(int style) {
- if (!L) return nullptr;
- //int orig_stack_top = lua_gettop(L);
- const char *name = nullptr;
- lua_rawgetp(L, LUA_REGISTRYINDEX, reinterpret_cast<void *>(this));
- lua_getfield(L, -1, "_TOKENSTYLES");
- lua_pushnil(L);
- while (lua_next(L, -2))
- if (lua_tointeger(L, -1) == style) {
- name = lua_tostring(L, -2); // no need to copy; will remain in memory
- lua_pop(L, 2); // value and key
- break;
- } else lua_pop(L, 1); // value
- lua_pop(L, 2); // _TOKENSTYLES, lexer object
- //assert(lua_gettop(L) == orig_stack_top);
- return name;
- }
-
- /**
- * Initializes the lexer once the `lexer.lpeg.home` and `lexer.name`
- * properties are set.
- */
- bool Init() {
- char home[FILENAME_MAX], lexer[50], theme[FILENAME_MAX];
- props.GetExpanded("lexer.lpeg.home", home);
- props.GetExpanded("lexer.name", lexer);
- props.GetExpanded("lexer.lpeg.color.theme", theme);
- if (!*home || !*lexer || !L) return false;
- //int orig_stack_top = lua_gettop(L);
-
- // Designate the currently running LexerLPeg instance.
- // This needs to be done prior to calling any Lua lexer code, particularly
- // when `own_lua` is `false`, as there may be multiple LexerLPeg instances
- // floating around, and the lexer module methods and metamethods need to
- // know which instance to use.
- lua_pushlightuserdata(L, reinterpret_cast<void *>(this));
- lua_setfield(L, LUA_REGISTRYINDEX, "sci_lexer_lpeg");
-
- // If necessary, load the lexer module and theme.
- lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
- if (lua_getfield(L, -1, "lexer") == LUA_TNIL) {
- lua_pop(L, 2); // nil and _LOADED
-
- // Modify `package.path` to find lexers.
- lua_getglobal(L, "package"), lua_getfield(L, -1, "path");
- int orig_path = luaL_ref(L, LUA_REGISTRYINDEX); // restore later
- lua_pushstring(L, home), lua_pushstring(L, "/?.lua"), lua_concat(L, 2);
- lua_setfield(L, -2, "path"), lua_pop(L, 1); // package
-
- // Load the lexer module.
- lua_getglobal(L, "require");
- lua_pushstring(L, "lexer");
- if (lua_pcall(L, 1, 1, 0) != LUA_OK) return (log_error(L), false);
- lua_pushinteger(L, SC_FOLDLEVELBASE);
- lua_setfield(L, -2, "FOLD_BASE");
- lua_pushinteger(L, SC_FOLDLEVELWHITEFLAG);
- lua_setfield(L, -2, "FOLD_BLANK");
- lua_pushinteger(L, SC_FOLDLEVELHEADERFLAG);
- lua_setfield(L, -2, "FOLD_HEADER");
- if (luaL_newmetatable(L, "sci_lexer")) {
- lua_pushcfunction(L, lexer_index), lua_setfield(L, -2, "__index");
- lua_pushcfunction(L, lexer_newindex), lua_setfield(L, -2, "__newindex");
- }
- lua_setmetatable(L, -2);
-
- // Restore `package.path`.
- lua_getglobal(L, "package");
- lua_getfield(L, -1, "path"), lua_setfield(L, -3, "path"); // lexer.path =
- lua_rawgeti(L, LUA_REGISTRYINDEX, orig_path), lua_setfield(L, -2, "path");
- luaL_unref(L, LUA_REGISTRYINDEX, orig_path), lua_pop(L, 1); // package
- } else lua_remove(L, -2); // _LOADED
-
- // Load the language lexer.
- if (lua_getfield(L, -1, "load") != LUA_TFUNCTION)
- return (log_error(L, "'lexer.load' function not found"), false);
- lua_pushstring(L, lexer), lua_pushnil(L), lua_pushboolean(L, 1);
- if (lua_pcall(L, 3, 1, 0) != LUA_OK) return (log_error(L), false);
- lua_remove(L, -2); // lexer module
- lua_pushlightuserdata(L, reinterpret_cast<void *>(&props));
- lua_setfield(L, -2, "_PROPS");
- lua_rawsetp(L, LUA_REGISTRYINDEX, reinterpret_cast<void *>(this));
-
- // Load the theme and set up styles.
- if (*theme) {
- if (!(strstr(theme, "/") || strstr(theme, "\\"))) { // theme name
- lua_pushstring(L, home);
- lua_pushstring(L, "/themes/");
- lua_pushstring(L, theme);
- lua_pushstring(L, ".lua");
- lua_concat(L, 4);
- } else lua_pushstring(L, theme); // path to theme
- if (luaL_loadfile(L, lua_tostring(L, -1)) != LUA_OK ||
- lua_pcall(L, 0, 0, 0) != LUA_OK) return (log_error(L), false);
- lua_pop(L, 1); // theme
- }
- if (!SetStyles()) return false;
-
- // If the lexer is a parent, it will have children in its _CHILDREN table.
- lua_rawgetp(L, LUA_REGISTRYINDEX, reinterpret_cast<void *>(this));
- if (lua_getfield(L, -1, "_CHILDREN") == LUA_TTABLE) {
- multilang = true;
- // Determine which styles are language whitespace styles
- // ([lang]_whitespace). This is necessary for determining which language
- // to start lexing with.
- char style_name[50];
- for (int i = 0; i <= STYLE_MAX; i++) {
- PrivateCall(i, reinterpret_cast<void *>(style_name));
- ws[i] = strstr(style_name, "whitespace") ? true : false;
- }
- }
- lua_pop(L, 2); // _CHILDREN, lexer object
-
- reinit = false;
- props.Set("lexer.lpeg.error", "", strlen("lexer.lpeg.error"), 0);
- //assert(lua_gettop(L) == orig_stack_top);
- return true;
- }
-
- /**
- * When *lparam* is `0`, returns the size of the buffer needed to store the
- * given string *str* in; otherwise copies *str* into the buffer *lparam* and
- * returns the number of bytes copied.
- * @param lparam `0` to get the number of bytes needed to store *str* or a
- * pointer to a buffer large enough to copy *str* into.
- * @param str The string to copy.
- * @return number of bytes needed to hold *str*
- */
- void *StringResult(long lparam, const char *str) {
- if (lparam) strcpy(reinterpret_cast<char *>(lparam), str);
- return reinterpret_cast<void *>(strlen(str));
- }
+ } else if ((strcmp(key, "fore") == 0 || strcmp(key, "back") == 0) &&
+ val) {
+ int msg = (*key == 'f') ? SCI_STYLESETFORE : SCI_STYLESETBACK;
+ int color = static_cast<int>(strtol(val, nullptr, 0));
+ if (*val == '#') { // #RRGGBB format; Scintilla format is 0xBBGGRR
+ color = static_cast<int>(strtol(val + 1, nullptr, 16));
+ color =
+ ((color & 0xFF0000) >> 16) | (color & 0xFF00) |
+ ((color & 0xFF) << 16); // convert to 0xBBGGRR
+ }
+ SS(sci, msg, num, color);
+ } else if (strcmp(key, "eolfilled") == 0 ||
+ strcmp(key, "noteolfilled") == 0)
+ SS(sci, SCI_STYLESETEOLFILLED, num, *key == 'e');
+ else if (strcmp(key, "characterset") == 0 && val)
+ SS(sci, SCI_STYLESETCHARACTERSET, num, static_cast<int>(atoi(val)));
+ else if (strcmp(key, "case") == 0 && val) {
+ if (*val == 'u')
+ SS(sci, SCI_STYLESETCASE, num, SC_CASE_UPPER);
+ else if (*val == 'l')
+ SS(sci, SCI_STYLESETCASE, num, SC_CASE_LOWER);
+ } else if (strcmp(key, "visible") == 0 || strcmp(key, "notvisible") == 0)
+ SS(sci, SCI_STYLESETVISIBLE, num, *key == 'v');
+ else if (strcmp(key, "changeable") == 0 ||
+ strcmp(key, "notchangeable") == 0)
+ SS(sci, SCI_STYLESETCHANGEABLE, num, *key == 'c');
+ else if (strcmp(key, "hotspot") == 0 || strcmp(key, "nothotspot") == 0)
+ SS(sci, SCI_STYLESETHOTSPOT, num, *key == 'h');
+ key = next;
+ }
+ free(style_copy);
+ }
+
+ /**
+ * Iterates through the lexer's `_TOKENSTYLES`, setting the style properties
+ * for all defined styles.
+ */
+ bool SetStyles() {
+ //int orig_stack_top = lua_gettop(L);
+ // If the lexer defines additional styles, set their properties first (if
+ // the user has not already defined them).
+ lua_rawgetp(L, LUA_REGISTRYINDEX, reinterpret_cast<void *>(this));
+ lua_getfield(L, -1, "_EXTRASTYLES");
+ lua_pushnil(L);
+ while (lua_next(L, -2)) {
+ if (lua_isstring(L, -2) && lua_isstring(L, -1)) {
+ lua_pushstring(L, "style."), lua_pushvalue(L, -3), lua_concat(L, 2);
+ if (!*props.Get(lua_tostring(L, -1)))
+ props.Set(
+ lua_tostring(L, -1), lua_tostring(L, -2), lua_rawlen(L, -1),
+ lua_rawlen(L, -2));
+ lua_pop(L, 1); // style name
+ }
+ lua_pop(L, 1); // value
+ }
+ lua_pop(L, 1); // _EXTRASTYLES
+
+ if (!SS || !sci) {
+ lua_pop(L, 1); // lexer object
+ // Skip, but do not report an error since `reinit` would remain `false`
+ // and subsequent calls to `Lex()` and `Fold()` would repeatedly call this
+ // function and error.
+ //assert(lua_gettop(L) == orig_stack_top);
+ return true;
+ }
+ lua_pushstring(L, "style.default"), expand_property(L);
+ SetStyle(STYLE_DEFAULT, lua_tostring(L, -1));
+ lua_pop(L, 1); // style
+ SS(sci, SCI_STYLECLEARALL, 0, 0); // set default styles
+ lua_getfield(L, -1, "_TOKENSTYLES");
+ lua_pushnil(L);
+ while (lua_next(L, -2)) {
+ if (lua_isstring(L, -2) && lua_isnumber(L, -1) &&
+ lua_tointeger(L, -1) != STYLE_DEFAULT) {
+ lua_pushstring(L, "style."), lua_pushvalue(L, -3), lua_concat(L, 2);
+ expand_property(L);
+ SetStyle(lua_tointeger(L, -2), lua_tostring(L, -1));
+ lua_pop(L, 1); // style
+ }
+ lua_pop(L, 1); // value
+ }
+ lua_pop(L, 2); // _TOKENSTYLES, lexer object
+ //assert(lua_gettop(L) == orig_stack_top);
+ return true;
+ }
+
+ /**
+ * Returns the style name for the given style number.
+ * @param style The style number to get the style name for.
+ * @return style name or nullptr
+ */
+ const char *GetStyleName(int style) {
+ if (!L) return nullptr;
+ //int orig_stack_top = lua_gettop(L);
+ const char *name = nullptr;
+ lua_rawgetp(L, LUA_REGISTRYINDEX, reinterpret_cast<void *>(this));
+ lua_getfield(L, -1, "_TOKENSTYLES");
+ lua_pushnil(L);
+ while (lua_next(L, -2))
+ if (lua_tointeger(L, -1) == style) {
+ name = lua_tostring(L, -2); // no need to copy; will remain in memory
+ lua_pop(L, 2); // value and key
+ break;
+ } else lua_pop(L, 1); // value
+ lua_pop(L, 2); // _TOKENSTYLES, lexer object
+ //assert(lua_gettop(L) == orig_stack_top);
+ return name;
+ }
+
+ /**
+ * Initializes the lexer once the `lexer.lpeg.home` and `lexer.name`
+ * properties are set.
+ */
+ bool Init() {
+ char home[FILENAME_MAX], lexer[50], theme[FILENAME_MAX];
+ props.GetExpanded("lexer.lpeg.home", home);
+ props.GetExpanded("lexer.name", lexer);
+ props.GetExpanded("lexer.lpeg.color.theme", theme);
+ if (!*home || !*lexer || !L) return false;
+ //int orig_stack_top = lua_gettop(L);
+
+ // Designate the currently running LexerLPeg instance.
+ // This needs to be done prior to calling any Lua lexer code, particularly
+ // when `own_lua` is `false`, as there may be multiple LexerLPeg instances
+ // floating around, and the lexer module methods and metamethods need to
+ // know which instance to use.
+ lua_pushlightuserdata(L, reinterpret_cast<void *>(this));
+ lua_setfield(L, LUA_REGISTRYINDEX, "sci_lexer_lpeg");
+
+ // If necessary, load the lexer module and theme.
+ lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
+ if (lua_getfield(L, -1, "lexer") == LUA_TNIL) {
+ lua_pop(L, 2); // nil and _LOADED
+
+ // Modify `package.path` to find lexers.
+ lua_getglobal(L, "package"), lua_getfield(L, -1, "path");
+ int orig_path = luaL_ref(L, LUA_REGISTRYINDEX); // restore later
+ lua_pushstring(L, home), lua_pushstring(L, "/?.lua"), lua_concat(L, 2);
+ lua_setfield(L, -2, "path"), lua_pop(L, 1); // package
+
+ // Load the lexer module.
+ lua_getglobal(L, "require");
+ lua_pushstring(L, "lexer");
+ if (lua_pcall(L, 1, 1, 0) != LUA_OK) return (log_error(L), false);
+ lua_pushinteger(L, SC_FOLDLEVELBASE);
+ lua_setfield(L, -2, "FOLD_BASE");
+ lua_pushinteger(L, SC_FOLDLEVELWHITEFLAG);
+ lua_setfield(L, -2, "FOLD_BLANK");
+ lua_pushinteger(L, SC_FOLDLEVELHEADERFLAG);
+ lua_setfield(L, -2, "FOLD_HEADER");
+ if (luaL_newmetatable(L, "sci_lexer")) {
+ lua_pushcfunction(L, lexer_index), lua_setfield(L, -2, "__index");
+ lua_pushcfunction(L, lexer_newindex), lua_setfield(L, -2, "__newindex");
+ }
+ lua_setmetatable(L, -2);
+
+ // Restore `package.path`.
+ lua_getglobal(L, "package");
+ lua_getfield(L, -1, "path"), lua_setfield(L, -3, "path"); // lexer.path =
+ lua_rawgeti(L, LUA_REGISTRYINDEX, orig_path), lua_setfield(L, -2, "path");
+ luaL_unref(L, LUA_REGISTRYINDEX, orig_path), lua_pop(L, 1); // package
+ } else lua_remove(L, -2); // _LOADED
+
+ // Load the language lexer.
+ if (lua_getfield(L, -1, "load") != LUA_TFUNCTION)
+ return (log_error(L, "'lexer.load' function not found"), false);
+ lua_pushstring(L, lexer), lua_pushnil(L), lua_pushboolean(L, 1);
+ if (lua_pcall(L, 3, 1, 0) != LUA_OK) return (log_error(L), false);
+ lua_remove(L, -2); // lexer module
+ lua_pushlightuserdata(L, reinterpret_cast<void *>(&props));
+ lua_setfield(L, -2, "_PROPS");
+ lua_rawsetp(L, LUA_REGISTRYINDEX, reinterpret_cast<void *>(this));
+
+ // Load the theme and set up styles.
+ if (*theme) {
+ if (!(strstr(theme, "/") || strstr(theme, "\\"))) { // theme name
+ lua_pushstring(L, home);
+ lua_pushstring(L, "/themes/");
+ lua_pushstring(L, theme);
+ lua_pushstring(L, ".lua");
+ lua_concat(L, 4);
+ } else lua_pushstring(L, theme); // path to theme
+ if (luaL_loadfile(L, lua_tostring(L, -1)) != LUA_OK ||
+ lua_pcall(L, 0, 0, 0) != LUA_OK) return (log_error(L), false);
+ lua_pop(L, 1); // theme
+ }
+ if (!SetStyles()) return false;
+
+ // If the lexer is a parent, it will have children in its _CHILDREN table.
+ lua_rawgetp(L, LUA_REGISTRYINDEX, reinterpret_cast<void *>(this));
+ if (lua_getfield(L, -1, "_CHILDREN") == LUA_TTABLE) {
+ multilang = true;
+ // Determine which styles are language whitespace styles
+ // ([lang]_whitespace). This is necessary for determining which language
+ // to start lexing with.
+ char style_name[50];
+ for (int i = 0; i <= STYLE_MAX; i++) {
+ PrivateCall(i, reinterpret_cast<void *>(style_name));
+ ws[i] = strstr(style_name, "whitespace") ? true : false;
+ }
+ }
+ lua_pop(L, 2); // _CHILDREN, lexer object
+
+ reinit = false;
+ props.Set("lexer.lpeg.error", "", strlen("lexer.lpeg.error"), 0);
+ //assert(lua_gettop(L) == orig_stack_top);
+ return true;
+ }
+
+ /**
+ * When *lparam* is `0`, returns the size of the buffer needed to store the
+ * given string *str* in; otherwise copies *str* into the buffer *lparam* and
+ * returns the number of bytes copied.
+ * @param lparam `0` to get the number of bytes needed to store *str* or a
+ * pointer to a buffer large enough to copy *str* into.
+ * @param str The string to copy.
+ * @return number of bytes needed to hold *str*
+ */
+ void *StringResult(long lparam, const char *str) {
+ if (lparam) strcpy(reinterpret_cast<char *>(lparam), str);
+ return reinterpret_cast<void *>(strlen(str));
+ }
public:
- /** Constructor. */
- LexerLPeg() : L(luaL_newstate()) {
- // Initialize the Lua state, load libraries, and set platform variables.
- if (!L) {
- fprintf(stderr, "Lua failed to initialize.\n");
- return;
- }
+ /** Constructor. */
+ LexerLPeg() : L(luaL_newstate()) {
+ // Initialize the Lua state, load libraries, and set platform variables.
+ if (!L) {
+ fprintf(stderr, "Lua failed to initialize.\n");
+ return;
+ }
#if LUA_VERSION_NUM < 502
- luaL_requiref(L, "", luaopen_base, 1), lua_pop(L, 1);
+ luaL_requiref(L, "", luaopen_base, 1), lua_pop(L, 1);
#else
- luaL_requiref(L, "_G", luaopen_base, 1), lua_pop(L, 1);
+ luaL_requiref(L, "_G", luaopen_base, 1), lua_pop(L, 1);
#endif
- luaL_requiref(L, LUA_TABLIBNAME, luaopen_table, 1), lua_pop(L, 1);
- luaL_requiref(L, LUA_STRLIBNAME, luaopen_string, 1), lua_pop(L, 1);
+ luaL_requiref(L, LUA_TABLIBNAME, luaopen_table, 1), lua_pop(L, 1);
+ luaL_requiref(L, LUA_STRLIBNAME, luaopen_string, 1), lua_pop(L, 1);
#if LUA_VERSION_NUM < 502
- // `package.searchpath()` emulation requires io.
- luaL_requiref(L, LUA_IOLIBNAME, luaopen_io, 1), lua_pop(L, 1);
+ // `package.searchpath()` emulation requires io.
+ luaL_requiref(L, LUA_IOLIBNAME, luaopen_io, 1), lua_pop(L, 1);
#endif
- luaL_requiref(L, LUA_LOADLIBNAME, luaopen_package, 1), lua_pop(L, 1);
- luaL_requiref(L, "lpeg", luaopen_lpeg, 1), lua_pop(L, 1);
+ luaL_requiref(L, LUA_LOADLIBNAME, luaopen_package, 1), lua_pop(L, 1);
+ luaL_requiref(L, "lpeg", luaopen_lpeg, 1), lua_pop(L, 1);
#if _WIN32
- lua_pushboolean(L, 1), lua_setglobal(L, "WIN32");
+ lua_pushboolean(L, 1), lua_setglobal(L, "WIN32");
#endif
#if __APPLE__
- lua_pushboolean(L, 1), lua_setglobal(L, "OSX");
+ lua_pushboolean(L, 1), lua_setglobal(L, "OSX");
#endif
#if GTK
- lua_pushboolean(L, 1), lua_setglobal(L, "GTK");
+ lua_pushboolean(L, 1), lua_setglobal(L, "GTK");
#endif
#if CURSES
- lua_pushboolean(L, 1), lua_setglobal(L, "CURSES");
+ lua_pushboolean(L, 1), lua_setglobal(L, "CURSES");
#endif
- }
-
- /** Destructor. */
- virtual ~LexerLPeg() = default;
-
- /** Destroys the lexer object. */
- void SCI_METHOD Release() override {
- if (own_lua && L)
- lua_close(L);
- else if (!own_lua) {
- lua_pushnil(L);
- lua_rawsetp(L, LUA_REGISTRYINDEX, reinterpret_cast<void *>(this));
- }
- delete this;
- }
-
- /**
- * Lexes the Scintilla document.
- * @param startPos The position in the document to start lexing at.
- * @param lengthDoc The number of bytes in the document to lex.
- * @param initStyle The initial style at position *startPos* in the document.
- * @param buffer The document interface.
- */
- void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position lengthDoc,
- int initStyle, IDocument *buffer) override {
- LexAccessor styler(buffer);
- if ((reinit && !Init()) || !L) {
- // Style everything in the default style.
- styler.StartAt(startPos);
- styler.StartSegment(startPos);
- styler.ColourTo(startPos + lengthDoc - 1, STYLE_DEFAULT);
- styler.Flush();
- return;
- }
- //int orig_stack_top = lua_gettop(L);
- lua_pushlightuserdata(L, reinterpret_cast<void *>(this));
- lua_setfield(L, LUA_REGISTRYINDEX, "sci_lexer_lpeg");
- lua_rawgetp(L, LUA_REGISTRYINDEX, reinterpret_cast<void *>(this));
- lua_pushlightuserdata(L, reinterpret_cast<void *>(buffer));
- lua_setfield(L, -2, "_BUFFER");
-
- // Ensure the lexer has a grammar.
- // This could be done in the lexer module's `lex()`, but for large files,
- // passing string arguments from C to Lua is expensive.
- if (!lua_getfield(L, -1, "_GRAMMAR")) {
- lua_pop(L, 2); // _GRAMMAR, lexer object
- // Style everything in the default style.
- styler.StartAt(startPos);
- styler.StartSegment(startPos);
- styler.ColourTo(startPos + lengthDoc - 1, STYLE_DEFAULT);
- styler.Flush();
- return;
- } else lua_pop(L, 1); // _GRAMMAR
-
- // Start from the beginning of the current style so LPeg matches it.
- // For multilang lexers, start at whitespace since embedded languages have
- // [lang]_whitespace styles. This is so LPeg can start matching child
- // languages instead of parent ones if necessary.
- if (startPos > 0) {
- Sci_PositionU i = startPos;
- while (i > 0 && styler.StyleAt(i - 1) == initStyle) i--;
- if (multilang)
- while (i > 0 && !ws[static_cast<size_t>(styler.StyleAt(i))]) i--;
- lengthDoc += startPos - i, startPos = i;
- }
-
- if (lua_getfield(L, -1, "lex") != LUA_TFUNCTION)
- return log_error(L, "'lexer.lex' function not found");
- lua_pushvalue(L, -2);
- lua_pushlstring(L, buffer->BufferPointer() + startPos, lengthDoc);
- lua_pushinteger(L, styler.StyleAt(startPos));
- if (lua_pcall(L, 3, 1, 0) != LUA_OK) return log_error(L);
- if (!lua_istable(L, -1))
- return log_error(L, "Table of tokens expected from 'lexer.lex'");
- // Style the text from the token table returned.
- int len = lua_rawlen(L, -1);
- if (len > 0) {
- int style = STYLE_DEFAULT;
- styler.StartAt(startPos);
- styler.StartSegment(startPos);
- lua_getfield(L, -2, "_TOKENSTYLES");
- // Loop through token-position pairs.
- for (int i = 1; i < len; i += 2) {
- style = STYLE_DEFAULT;
- if (lua_rawgeti(L, -2, i), lua_rawget(L, -2))
- style = lua_tointeger(L, -1);
- lua_pop(L, 1); // _TOKENSTYLES[token]
- lua_rawgeti(L, -2, i + 1); // pos
- unsigned int position = lua_tointeger(L, -1) - 1;
- lua_pop(L, 1); // pos
- if (style >= 0 && style <= STYLE_MAX)
- styler.ColourTo(startPos + position - 1, style);
- else
- log_error(L, "Bad style number");
- if (position > startPos + lengthDoc) break;
- }
- lua_pop(L, 1); // _TOKENSTYLES
- styler.ColourTo(startPos + lengthDoc - 1, style);
- styler.Flush();
- }
- lua_pop(L, 2); // token table returned, lexer object
- //assert(lua_gettop(L) == orig_stack_top);
- }
-
- /**
- * Folds the Scintilla document.
- * @param startPos The position in the document to start folding at.
- * @param lengthDoc The number of bytes in the document to fold.
- * @param initStyle The initial style at position *startPos* in the document.
- * @param buffer The document interface.
- */
- void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position lengthDoc,
- int, IDocument *buffer) override {
- if ((reinit && !Init()) || !L) return;
- //int orig_stack_top = lua_gettop(L);
- lua_pushlightuserdata(L, reinterpret_cast<void *>(this));
- lua_setfield(L, LUA_REGISTRYINDEX, "sci_lexer_lpeg");
- lua_rawgetp(L, LUA_REGISTRYINDEX, reinterpret_cast<void *>(this));
- lua_pushlightuserdata(L, reinterpret_cast<void *>(buffer));
- lua_setfield(L, -2, "_BUFFER");
- LexAccessor styler(buffer);
-
- if (lua_getfield(L, -1, "fold") != LUA_TFUNCTION)
- return log_error(L, "'lexer.fold' function not found");
- lua_insert(L, -2);
- Sci_Position currentLine = styler.GetLine(startPos);
- lua_pushlstring(L, buffer->BufferPointer() + startPos, lengthDoc);
- lua_pushinteger(L, startPos);
- lua_pushinteger(L, currentLine);
- lua_pushinteger(L, styler.LevelAt(currentLine) & SC_FOLDLEVELNUMBERMASK);
- if (lua_pcall(L, 5, 1, 0) != LUA_OK) return log_error(L);
- if (!lua_istable(L, -1))
- return log_error(L, "Table of folds expected from 'lexer.fold'");
- // Fold the text from the fold table returned.
- lua_pushnil(L);
- while (lua_next(L, -2)) { // line = level
- styler.SetLevel(lua_tointeger(L, -2), lua_tointeger(L, -1));
- lua_pop(L, 1); // level
- }
- lua_pop(L, 1); // fold table returned
- //assert(lua_gettop(L) == orig_stack_top);
- }
-
- /** This lexer implements the original lexer interface. */
- int SCI_METHOD Version() const override { return lvOriginal; }
- /** Returning property names is not implemented. */
- const char * SCI_METHOD PropertyNames() override { return ""; }
- /** Returning property types is not implemented. */
- int SCI_METHOD PropertyType(const char *) override { return 0; }
- /** Returning property descriptions is not implemented. */
- const char * SCI_METHOD DescribeProperty(const char *) override { return ""; }
-
- /**
- * Sets the *key* lexer property to *value*.
- * If *key* starts with "style.", also set the style for the token.
- * @param key The string keyword.
- * @param val The string value.
- */
- Sci_Position SCI_METHOD PropertySet(const char *key,
- const char *value) override {
- props.Set(key, value, strlen(key), strlen(value));
- if (reinit)
- Init();
- else if (L && SS && sci && strncmp(key, "style.", 6) == 0) {
- //int orig_stack_top = lua_gettop(L);
- lua_pushlightuserdata(L, reinterpret_cast<void *>(this));
- lua_setfield(L, LUA_REGISTRYINDEX, "sci_lexer_lpeg");
- lua_rawgetp(L, LUA_REGISTRYINDEX, reinterpret_cast<void *>(this));
- lua_getfield(L, -1, "_TOKENSTYLES");
- if (lua_pushstring(L, key + 6), lua_rawget(L, -2) == LUA_TNUMBER) {
- lua_pushstring(L, key), expand_property(L);
- int style_num = lua_tointeger(L, -2);
- SetStyle(style_num, lua_tostring(L, -1));
- if (style_num == STYLE_DEFAULT)
- // Assume a theme change, with the default style being set first.
- // Subsequent style settings will be based on the default.
- SS(sci, SCI_STYLECLEARALL, 0, 0);
- }
- lua_pop(L, 4); // style, style number, _TOKENSTYLES, lexer object
- //assert(lua_gettop(L) == orig_stack_top);
- }
- return -1; // no need to re-lex
- }
-
- /** Returning keyword list descriptions is not implemented. */
- const char * SCI_METHOD DescribeWordListSets() override { return ""; }
- /** Setting keyword lists is not applicable. */
- Sci_Position SCI_METHOD WordListSet(int, const char *) override { return -1; }
-
- /**
- * Allows for direct communication between the application and the lexer.
- * The application uses this to set `SS`, `sci`, `L`, and lexer properties,
- * and to retrieve style names.
- * @param code The communication code.
- * @param arg The argument.
- * @return void *data
- */
- void * SCI_METHOD PrivateCall(int code, void *arg) override {
- auto lParam = reinterpret_cast<sptr_t>(arg);
- const char *val = nullptr;
- switch(code) {
- case SCI_GETDIRECTFUNCTION:
- SS = reinterpret_cast<SciFnDirect>(lParam);
- return nullptr;
- case SCI_SETDOCPOINTER:
- sci = lParam;
- return nullptr;
- case SCI_CHANGELEXERSTATE:
- if (own_lua) lua_close(L);
- L = reinterpret_cast<lua_State *>(lParam);
- own_lua = false;
- return nullptr;
- case SCI_SETLEXERLANGUAGE:
- char lexer_name[50];
- props.GetExpanded("lexer.name", lexer_name);
- if (strcmp(lexer_name, reinterpret_cast<const char *>(arg)) != 0) {
- reinit = true;
- props.Set("lexer.lpeg.error", "", strlen("lexer.lpeg.error"), 0);
- PropertySet("lexer.name", reinterpret_cast<const char *>(arg));
- } else if (L)
- own_lua ? SetStyles() : Init();
- return nullptr;
- case SCI_GETLEXERLANGUAGE:
- if (L) {
- //int orig_stack_top = lua_gettop(L);
- lua_rawgetp(L, LUA_REGISTRYINDEX, reinterpret_cast<void *>(this));
- lua_getfield(L, -1, "_NAME");
- if (SS && sci && multilang) {
- int pos = SS(sci, SCI_GETCURRENTPOS, 0, 0);
- while (pos >= 0 && !ws[SS(sci, SCI_GETSTYLEAT, pos, 0)]) pos--;
- const char *name = nullptr, *p = nullptr;
- if (pos >= 0) {
- name = GetStyleName(SS(sci, SCI_GETSTYLEAT, pos, 0));
- if (name) p = strstr(name, "_whitespace");
- }
- if (!name) name = lua_tostring(L, -1); // "lexer:lexer" fallback
- if (!p) p = name + strlen(name); // "lexer:lexer" fallback
- lua_pushstring(L, "/");
- lua_pushlstring(L, name, p - name);
- lua_concat(L, 3);
- }
- val = lua_tostring(L, -1); // no need to copy; will remain in memory
- lua_pop(L, 2); // lexer_name or lexer language string, lexer object
- //assert(lua_gettop(L) == orig_stack_top);
- }
- return StringResult(lParam, val ? val : "null");
- case SCI_GETSTATUS:
- return StringResult(lParam, props.Get("lexer.lpeg.error"));
- default: // style-related
- if (code >= 0 && code <= STYLE_MAX) { // retrieve style names
- val = GetStyleName(code);
- return StringResult(lParam, val ? val : "Not Available");
- } else return nullptr;
- }
- }
-
- /** Constructs a new instance of the lexer. */
- static ILexer *LexerFactoryLPeg() { return new LexerLPeg(); }
+ }
+
+ /** Destructor. */
+ virtual ~LexerLPeg() = default;
+
+ /** Destroys the lexer object. */
+ void SCI_METHOD Release() override {
+ if (own_lua && L)
+ lua_close(L);
+ else if (!own_lua) {
+ lua_pushnil(L);
+ lua_rawsetp(L, LUA_REGISTRYINDEX, reinterpret_cast<void *>(this));
+ }
+ delete this;
+ }
+
+ /**
+ * Lexes the Scintilla document.
+ * @param startPos The position in the document to start lexing at.
+ * @param lengthDoc The number of bytes in the document to lex.
+ * @param initStyle The initial style at position *startPos* in the document.
+ * @param buffer The document interface.
+ */
+ void SCI_METHOD Lex(
+ Sci_PositionU startPos, Sci_Position lengthDoc, int initStyle,
+ IDocument *buffer) override
+ {
+ LexAccessor styler(buffer);
+ if ((reinit && !Init()) || !L) {
+ // Style everything in the default style.
+ styler.StartAt(startPos);
+ styler.StartSegment(startPos);
+ styler.ColourTo(startPos + lengthDoc - 1, STYLE_DEFAULT);
+ styler.Flush();
+ return;
+ }
+ //int orig_stack_top = lua_gettop(L);
+ lua_pushlightuserdata(L, reinterpret_cast<void *>(this));
+ lua_setfield(L, LUA_REGISTRYINDEX, "sci_lexer_lpeg");
+ lua_rawgetp(L, LUA_REGISTRYINDEX, reinterpret_cast<void *>(this));
+ lua_pushlightuserdata(L, reinterpret_cast<void *>(buffer));
+ lua_setfield(L, -2, "_BUFFER");
+
+ // Ensure the lexer has a grammar.
+ // This could be done in the lexer module's `lex()`, but for large files,
+ // passing string arguments from C to Lua is expensive.
+ if (!lua_getfield(L, -1, "_GRAMMAR")) {
+ lua_pop(L, 2); // _GRAMMAR, lexer object
+ // Style everything in the default style.
+ styler.StartAt(startPos);
+ styler.StartSegment(startPos);
+ styler.ColourTo(startPos + lengthDoc - 1, STYLE_DEFAULT);
+ styler.Flush();
+ return;
+ } else lua_pop(L, 1); // _GRAMMAR
+
+ // Start from the beginning of the current style so LPeg matches it.
+ // For multilang lexers, start at whitespace since embedded languages have
+ // [lang]_whitespace styles. This is so LPeg can start matching child
+ // languages instead of parent ones if necessary.
+ if (startPos > 0) {
+ Sci_PositionU i = startPos;
+ while (i > 0 && styler.StyleAt(i - 1) == initStyle) i--;
+ if (multilang)
+ while (i > 0 && !ws[static_cast<size_t>(styler.StyleAt(i))]) i--;
+ lengthDoc += startPos - i, startPos = i;
+ }
+
+ if (lua_getfield(L, -1, "lex") != LUA_TFUNCTION)
+ return log_error(L, "'lexer.lex' function not found");
+ lua_pushvalue(L, -2);
+ lua_pushlstring(L, buffer->BufferPointer() + startPos, lengthDoc);
+ lua_pushinteger(L, styler.StyleAt(startPos));
+ if (lua_pcall(L, 3, 1, 0) != LUA_OK) return log_error(L);
+ if (!lua_istable(L, -1))
+ return log_error(L, "Table of tokens expected from 'lexer.lex'");
+ // Style the text from the token table returned.
+ int len = lua_rawlen(L, -1);
+ if (len > 0) {
+ int style = STYLE_DEFAULT;
+ styler.StartAt(startPos);
+ styler.StartSegment(startPos);
+ lua_getfield(L, -2, "_TOKENSTYLES");
+ // Loop through token-position pairs.
+ for (int i = 1; i < len; i += 2) {
+ style = STYLE_DEFAULT;
+ if (lua_rawgeti(L, -2, i), lua_rawget(L, -2))
+ style = lua_tointeger(L, -1);
+ lua_pop(L, 1); // _TOKENSTYLES[token]
+ lua_rawgeti(L, -2, i + 1); // pos
+ unsigned int position = lua_tointeger(L, -1) - 1;
+ lua_pop(L, 1); // pos
+ if (style >= 0 && style <= STYLE_MAX)
+ styler.ColourTo(startPos + position - 1, style);
+ else
+ log_error(L, "Bad style number");
+ if (position > startPos + lengthDoc) break;
+ }
+ lua_pop(L, 1); // _TOKENSTYLES
+ styler.ColourTo(startPos + lengthDoc - 1, style);
+ styler.Flush();
+ }
+ lua_pop(L, 2); // token table returned, lexer object
+ //assert(lua_gettop(L) == orig_stack_top);
+ }
+
+ /**
+ * Folds the Scintilla document.
+ * @param startPos The position in the document to start folding at.
+ * @param lengthDoc The number of bytes in the document to fold.
+ * @param initStyle The initial style at position *startPos* in the document.
+ * @param buffer The document interface.
+ */
+ void SCI_METHOD Fold(
+ Sci_PositionU startPos, Sci_Position lengthDoc, int, IDocument *buffer)
+ override
+ {
+ if ((reinit && !Init()) || !L) return;
+ //int orig_stack_top = lua_gettop(L);
+ lua_pushlightuserdata(L, reinterpret_cast<void *>(this));
+ lua_setfield(L, LUA_REGISTRYINDEX, "sci_lexer_lpeg");
+ lua_rawgetp(L, LUA_REGISTRYINDEX, reinterpret_cast<void *>(this));
+ lua_pushlightuserdata(L, reinterpret_cast<void *>(buffer));
+ lua_setfield(L, -2, "_BUFFER");
+ LexAccessor styler(buffer);
+
+ if (lua_getfield(L, -1, "fold") != LUA_TFUNCTION)
+ return log_error(L, "'lexer.fold' function not found");
+ lua_insert(L, -2);
+ Sci_Position currentLine = styler.GetLine(startPos);
+ lua_pushlstring(L, buffer->BufferPointer() + startPos, lengthDoc);
+ lua_pushinteger(L, startPos);
+ lua_pushinteger(L, currentLine);
+ lua_pushinteger(L, styler.LevelAt(currentLine) & SC_FOLDLEVELNUMBERMASK);
+ if (lua_pcall(L, 5, 1, 0) != LUA_OK) return log_error(L);
+ if (!lua_istable(L, -1))
+ return log_error(L, "Table of folds expected from 'lexer.fold'");
+ // Fold the text from the fold table returned.
+ lua_pushnil(L);
+ while (lua_next(L, -2)) { // line = level
+ styler.SetLevel(lua_tointeger(L, -2), lua_tointeger(L, -1));
+ lua_pop(L, 1); // level
+ }
+ lua_pop(L, 1); // fold table returned
+ //assert(lua_gettop(L) == orig_stack_top);
+ }
+
+ /** This lexer implements the original lexer interface. */
+ int SCI_METHOD Version() const override { return lvOriginal; }
+ /** Returning property names is not implemented. */
+ const char * SCI_METHOD PropertyNames() override { return ""; }
+ /** Returning property types is not implemented. */
+ int SCI_METHOD PropertyType(const char *) override { return 0; }
+ /** Returning property descriptions is not implemented. */
+ const char * SCI_METHOD DescribeProperty(const char *) override { return ""; }
+
+ /**
+ * Sets the *key* lexer property to *value*.
+ * If *key* starts with "style.", also set the style for the token.
+ * @param key The string keyword.
+ * @param val The string value.
+ */
+ Sci_Position SCI_METHOD PropertySet(
+ const char *key, const char *value) override
+ {
+ props.Set(key, value, strlen(key), strlen(value));
+ if (reinit)
+ Init();
+ else if (L && SS && sci && strncmp(key, "style.", 6) == 0) {
+ //int orig_stack_top = lua_gettop(L);
+ lua_pushlightuserdata(L, reinterpret_cast<void *>(this));
+ lua_setfield(L, LUA_REGISTRYINDEX, "sci_lexer_lpeg");
+ lua_rawgetp(L, LUA_REGISTRYINDEX, reinterpret_cast<void *>(this));
+ lua_getfield(L, -1, "_TOKENSTYLES");
+ if (lua_pushstring(L, key + 6), lua_rawget(L, -2) == LUA_TNUMBER) {
+ lua_pushstring(L, key), expand_property(L);
+ int style_num = lua_tointeger(L, -2);
+ SetStyle(style_num, lua_tostring(L, -1));
+ if (style_num == STYLE_DEFAULT)
+ // Assume a theme change, with the default style being set first.
+ // Subsequent style settings will be based on the default.
+ SS(sci, SCI_STYLECLEARALL, 0, 0);
+ }
+ lua_pop(L, 4); // style, style number, _TOKENSTYLES, lexer object
+ //assert(lua_gettop(L) == orig_stack_top);
+ }
+ return -1; // no need to re-lex
+ }
+
+ /** Returning keyword list descriptions is not implemented. */
+ const char * SCI_METHOD DescribeWordListSets() override { return ""; }
+ /** Setting keyword lists is not applicable. */
+ Sci_Position SCI_METHOD WordListSet(int, const char *) override { return -1; }
+
+ /**
+ * Allows for direct communication between the application and the lexer.
+ * The application uses this to set `SS`, `sci`, `L`, and lexer properties,
+ * and to retrieve style names.
+ * @param code The communication code.
+ * @param arg The argument.
+ * @return void *data
+ */
+ void * SCI_METHOD PrivateCall(int code, void *arg) override {
+ auto lParam = reinterpret_cast<sptr_t>(arg);
+ const char *val = nullptr;
+ switch(code) {
+ case SCI_GETDIRECTFUNCTION:
+ SS = reinterpret_cast<SciFnDirect>(lParam);
+ return nullptr;
+ case SCI_SETDOCPOINTER:
+ sci = lParam;
+ return nullptr;
+ case SCI_CHANGELEXERSTATE:
+ if (own_lua) lua_close(L);
+ L = reinterpret_cast<lua_State *>(lParam);
+ own_lua = false;
+ return nullptr;
+ case SCI_SETLEXERLANGUAGE:
+ char lexer_name[50];
+ props.GetExpanded("lexer.name", lexer_name);
+ if (strcmp(lexer_name, reinterpret_cast<const char *>(arg)) != 0) {
+ reinit = true;
+ props.Set("lexer.lpeg.error", "", strlen("lexer.lpeg.error"), 0);
+ PropertySet("lexer.name", reinterpret_cast<const char *>(arg));
+ } else if (L)
+ own_lua ? SetStyles() : Init();
+ return nullptr;
+ case SCI_GETLEXERLANGUAGE:
+ if (L) {
+ //int orig_stack_top = lua_gettop(L);
+ lua_rawgetp(L, LUA_REGISTRYINDEX, reinterpret_cast<void *>(this));
+ lua_getfield(L, -1, "_NAME");
+ if (SS && sci && multilang) {
+ int pos = SS(sci, SCI_GETCURRENTPOS, 0, 0);
+ while (pos >= 0 && !ws[SS(sci, SCI_GETSTYLEAT, pos, 0)]) pos--;
+ const char *name = nullptr, *p = nullptr;
+ if (pos >= 0) {
+ name = GetStyleName(SS(sci, SCI_GETSTYLEAT, pos, 0));
+ if (name) p = strstr(name, "_whitespace");
+ }
+ if (!name) name = lua_tostring(L, -1); // "lexer:lexer" fallback
+ if (!p) p = name + strlen(name); // "lexer:lexer" fallback
+ lua_pushstring(L, "/");
+ lua_pushlstring(L, name, p - name);
+ lua_concat(L, 3);
+ }
+ val = lua_tostring(L, -1); // no need to copy; will remain in memory
+ lua_pop(L, 2); // lexer_name or lexer language string, lexer object
+ //assert(lua_gettop(L) == orig_stack_top);
+ }
+ return StringResult(lParam, val ? val : "null");
+ case SCI_GETSTATUS:
+ return StringResult(lParam, props.Get("lexer.lpeg.error"));
+ default: // style-related
+ if (code >= 0 && code <= STYLE_MAX) { // retrieve style names
+ val = GetStyleName(code);
+ return StringResult(lParam, val ? val : "Not Available");
+ } else return nullptr;
+ }
+ }
+
+ /** Constructs a new instance of the lexer. */
+ static ILexer *LexerFactoryLPeg() { return new LexerLPeg(); }
};
LexerModule lmLPeg(SCLEX_LPEG, LexerLPeg::LexerFactoryLPeg, "lpeg");
@@ -812,7 +819,7 @@ LexerModule lmLPeg(SCLEX_LPEG, LexerLPeg::LexerFactoryLPeg, "lpeg");
using namespace Scintilla;
static void LPegLex(Sci_PositionU, Sci_Position, int, WordList*[], Accessor&) {
- return;
+ return;
}
LexerModule lmLPeg(SCLEX_LPEG, LPegLex, "lpeg");