scite-context-lexer-cpp.lua /size: 6350 b    last modification: 2020-07-01 14:35
1local info = {
2    version   = 1.002,
3    comment   = "scintilla lpeg lexer for cpp",
4    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5    copyright = "PRAGMA ADE / ConTeXt Development Team",
6    license   = "see context related readme files",
7}
8
9-- looks liks the original cpp lexer but web ready (so nothing special here yet)
10
11local P, R, S = lpeg.P, lpeg.R, lpeg.S
12
13local lexer       = require("scite-context-lexer")
14local context     = lexer.context
15local patterns    = context.patterns
16
17local token       = lexer.token
18local exact_match = lexer.exact_match
19
20local cpplexer    = lexer.new("cpp","scite-context-lexer-cpp")
21local whitespace  = cpplexer.whitespace
22
23local keywords = { -- copied from cpp.lua
24    -- c
25    "asm", "auto", "break", "case", "const", "continue", "default", "do", "else",
26    "extern", "false", "for", "goto", "if", "inline", "register", "return",
27    "sizeof", "static", "switch", "true", "typedef", "volatile", "while",
28    "restrict",
29    -- hm
30    "_Bool", "_Complex", "_Pragma", "_Imaginary",
31    "boolean",
32    -- c++.
33    "catch", "class", "const_cast", "delete", "dynamic_cast", "explicit",
34    "export", "friend", "mutable", "namespace", "new", "operator", "private",
35    "protected", "public", "signals", "slots", "reinterpret_cast",
36    "static_assert", "static_cast", "template", "this", "throw", "try", "typeid",
37    "typename", "using", "virtual"
38}
39
40local datatypes = { -- copied from cpp.lua
41    "bool", "char", "double", "enum", "float", "int", "long", "short", "signed",
42    "struct", "union", "unsigned", "void"
43}
44
45local macros = { -- copied from cpp.lua
46    "define", "elif", "else", "endif", "error", "if", "ifdef", "ifndef", "import",
47    "include", "line", "pragma", "undef", "using", "warning"
48}
49
50local luatexs = {
51    "word", "halfword", "quarterword", "scaledwhd", "scaled", "pointer", "glueratio", "strnumber",
52    "dumpstream", "memoryword",
53}
54
55local space         = patterns.space -- S(" \n\r\t\f\v")
56local any           = patterns.any
57local restofline    = patterns.restofline
58local startofline   = patterns.startofline
59
60local squote        = P("'")
61local dquote        = P('"')
62local period        = P(".")
63local escaped       = P("\\") * P(1)
64local slashes       = P("//")
65local begincomment  = P("/*")
66local endcomment    = P("*/")
67local percent       = P("%")
68
69local hexadecimal   = patterns.hexadecimal
70local decimal       = patterns.decimal
71local float         = patterns.float
72local integer       = P("-")^-1 * (hexadecimal + decimal) -- also in patterns ?
73
74local spacing       = token(whitespace, space^1)
75local rest          = token("default", any)
76
77local shortcomment  = token("comment", slashes * restofline^0)
78local longcomment   = token("comment", begincomment * (1-endcomment)^0 * endcomment^-1)
79
80local shortstring   = token("quote",  dquote) -- can be shared
81                    * token("string", (escaped + (1-dquote))^0)
82                    * token("quote",  dquote)
83                    + token("quote",  squote)
84                    * token("string", (escaped + (1-squote))^0)
85                    * token("quote",  squote)
86
87local number        = token("number", float + integer)
88
89local validword     = R("AZ","az","__") * R("AZ","az","__","09")^0
90local identifier    = token("default",validword)
91
92local operator      = token("special", S("+-*/%^!=<>;:{}[]().&|?~"))
93
94----- optionalspace = spacing^0
95
96local p_keywords    = exact_match(keywords)
97local p_datatypes   = exact_match(datatypes)
98local p_macros      = exact_match(macros)
99local p_luatexs     = exact_match(luatexs)
100
101local keyword       = token("keyword", p_keywords)
102local datatype      = token("keyword", p_datatypes)
103local identifier    = token("default", validword)
104local luatex        = token("command", p_luatexs)
105
106local macro         = token("data", #P("#") * startofline * P("#") * S("\t ")^0 * p_macros)
107
108cpplexer._rules = {
109    { "whitespace",   spacing      },
110    { "keyword",      keyword      },
111    { "type",         datatype     },
112    { "luatex",       luatex       },
113    { "identifier",   identifier   },
114    { "string",       shortstring  },
115    { "longcomment",  longcomment  },
116    { "shortcomment", shortcomment },
117    { "number",       number       },
118    { "macro",        macro        },
119    { "operator",     operator     },
120    { "rest",         rest         },
121}
122
123local web = lexer.loadluafile("scite-context-lexer-web-snippets")
124
125if web then
126
127    lexer.inform("supporting web snippets in cpp lexer")
128
129    cpplexer._rules_web = {
130        { "whitespace",   spacing      },
131        { "keyword",      keyword      },
132        { "type",         datatype     },
133        { "luatex",       luatex       },
134        { "identifier",   identifier   },
135        { "string",       shortstring  },
136        { "longcomment",  longcomment  },
137        { "shortcomment", shortcomment },
138        { "web",          web.pattern  },
139        { "number",       number       },
140        { "macro",        macro        },
141        { "operator",     operator     },
142        { "rest",         rest         },
143    }
144
145else
146
147    lexer.report("not supporting web snippets in cpp lexer")
148
149    cpplexer._rules_web = {
150        { "whitespace",   spacing      },
151        { "keyword",      keyword      },
152        { "type",         datatype     },
153        { "luatex",       luatex       },
154        { "identifier",   identifier   },
155        { "string",       shortstring  },
156        { "longcomment",  longcomment  },
157        { "shortcomment", shortcomment },
158        { "number",       number       },
159        { "macro",        macro        },
160        { "operator",     operator     },
161        { "rest",         rest         },
162    }
163
164end
165
166cpplexer._tokenstyles = context.styleset
167
168cpplexer._foldpattern = P("/*") + P("*/") + S("{}") -- separate entry else interference (singular?)
169
170cpplexer._foldsymbols = {
171    _patterns = {
172        "[{}]",
173        "/%*",
174        "%*/",
175    },
176 -- ["data"] = { -- macro
177 --     ["region"]    =  1,
178 --     ["endregion"] = -1,
179 --     ["if"]        =  1,
180 --     ["ifdef"]     =  1,
181 --     ["ifndef"]    =  1,
182 --     ["endif"]     = -1,
183 -- },
184    ["special"] = { -- operator
185        ["{"] =  1,
186        ["}"] = -1,
187    },
188    ["comment"] = {
189        ["/*"] =  1,
190        ["*/"] = -1,
191    }
192}
193
194-- -- by indentation:
195
196cpplexer._foldpatterns = nil
197cpplexer._foldsymbols  = nil
198
199return cpplexer
200