1 2 /* This version of microEmacs is based on the public domain C 3 * version written by Dave G. Conroy. 4 * The D programming language version is written by Walter Bright. 5 * http://www.digitalmars.com/d/ 6 * This program is in the public domain. 7 */ 8 9 /* This is the C++ syntax highligher. 10 */ 11 12 module syntaxcpp; 13 14 import core.stdc.stdio; 15 import core.stdc.ctype; 16 17 import std.utf; 18 19 import ed; 20 import buffer; 21 import window; 22 import main; 23 import display; 24 import random; 25 26 /******************************** 27 * Returns: 28 * starting syntax state of next line 29 */ 30 SyntaxState syntaxHighlightCPP(SyntaxState syntaxState, const(char)[] text, attr_t[] attr) 31 { 32 size_t i = 0; 33 34 switch (syntaxState.syntax) 35 { 36 case Syntax..string: 37 case Syntax.singleString: 38 { 39 const quote = (syntaxState.syntax == Syntax..string) ? '"' : 40 '\''; 41 const istart = i; 42 bool escape; 43 while (i < text.length) 44 { 45 if (text[i] == quote && !escape) 46 { 47 ++i; 48 attr[istart .. i] = config..string; 49 goto Loop; 50 } 51 else if (text[i] == '\\') 52 escape ^= true; 53 else 54 escape = false; 55 ++i; 56 } 57 attr[istart .. i] = config..string; 58 return SyntaxState(syntaxState.syntax); 59 } 60 61 case Syntax.comment: 62 { 63 // it's /* */ comment 64 const istart = i; 65 while (i < text.length) 66 { 67 if (text[i] == '*' && i + 1 < text.length && text[i + 1] == '/') 68 { 69 i += 2; 70 attr[istart .. i] = config.comment; 71 goto Loop; 72 } 73 ++i; 74 } 75 attr[istart .. i] = config.comment; 76 return SyntaxState(Syntax.comment); 77 } 78 79 default: 80 break; 81 } 82 83 Loop: 84 while (i < text.length) 85 { 86 const c = text[i]; 87 switch (c) 88 { 89 case 'a': .. case 'z': 90 case 'A': .. case 'Z': 91 case '_': 92 Idstart: 93 { 94 const istart = i; 95 ++i; 96 while (i < text.length) 97 { 98 const ci = text[i]; 99 if (isalnum(ci) || ci == '_' || ci & 0x80) 100 { 101 ++i; 102 continue; 103 } 104 break; 105 } 106 const id = text[istart .. i]; 107 attr[istart .. i] = isCPPKeyword(id) ? config.keyword : config.normattr; 108 continue; 109 } 110 111 case '/': 112 { 113 const istart = i; 114 ++i; 115 if (i < text.length) 116 { 117 if (text[i] == '/') 118 { 119 attr[istart .. text.length] = config.comment; 120 return SyntaxState(Syntax.normal); 121 } 122 123 if (text[i] == '*') 124 { 125 ++i; 126 while (i < text.length) 127 { 128 if (text[i] == '*' && i + 1 < text.length && text[i + 1] == '/') 129 { 130 i += 2; 131 attr[istart .. i] = config.comment; 132 continue Loop; 133 } 134 ++i; 135 } 136 attr[istart .. i] = config.comment; 137 return SyntaxState(Syntax.comment); 138 } 139 } 140 continue; 141 } 142 143 case '"': 144 case '\'': 145 { 146 const istart = i; 147 bool escape; 148 ++i; 149 while (i < text.length) 150 { 151 if (text[i] == c && !escape) 152 { 153 ++i; 154 attr[istart .. i] = config..string; 155 continue Loop; 156 } 157 else if (text[i] == '\\') 158 escape ^= true; 159 else 160 escape = false; 161 ++i; 162 } 163 attr[istart .. i] = config..string; 164 return SyntaxState(c == '"' ? Syntax..string : 165 Syntax.singleString); 166 } 167 168 default: 169 if (text[i] & 0x80) 170 goto Idstart; 171 attr[i] = config.normattr; 172 ++i; 173 continue; 174 } 175 /* 176 switch (syntaxState.syntax) 177 { 178 case Syntax.normal: 179 break; 180 181 case Syntax.string: 182 case Syntax.singleString: 183 break; 184 185 case Syntax.comment: 186 break; 187 188 default: 189 assert(0); 190 } 191 */ 192 } 193 return SyntaxState(Syntax.normal); 194 } 195 196 private bool isCPPKeyword(const(char)[] s) 197 { 198 switch (s) 199 { 200 case "alignas": 201 case "const_cast": 202 case "for": 203 case "public": 204 case "thread_local ": 205 case "alignof": 206 case "continue": 207 case "friend": 208 case "register": 209 case "throw": 210 case "asm": 211 case "decltype": 212 case "goto": 213 case "reinterpret_cast": 214 case "true ": 215 case "auto": 216 case "default": 217 case "if": 218 case "requires": 219 case "try ": 220 case "bool": 221 case "delete": 222 case "inline": 223 case "return": 224 case "typedef ": 225 case "break": 226 case "do": 227 case "int": 228 case "short": 229 case "typeid ": 230 case "case": 231 case "double": 232 case "long": 233 case "signed": 234 case "typename ": 235 case "catch": 236 case "dynamic_cast": 237 case "mutable": 238 case "sizeof": 239 case "union ": 240 case "char": 241 case "else": 242 case "namespace": 243 case "static": 244 case "unsigned ": 245 case "char16_t": 246 case "enum": 247 case "new": 248 case "static_assert": 249 case "using ": 250 case "char32_t": 251 case "explicit": 252 case "noexcept": 253 case "static_cast": 254 case "virtual ": 255 case "class": 256 case "export": 257 case "nullptr": 258 case "struct": 259 case "void ": 260 case "concept": 261 case "extern": 262 case "operator": 263 case "switch": 264 case "volatile ": 265 case "const": 266 case "false": 267 case "private": 268 case "template": 269 case "wchar_t ": 270 case "constexpr": 271 case "float": 272 case "protected": 273 case "this": 274 case "while": 275 276 case "and": 277 case "and_eq": 278 case "bitand": 279 case "bitor": 280 case "compl": 281 case "not ": 282 case "not_eq": 283 case "or": 284 case "or_eq": 285 case "xor": 286 case "xor_eq ": 287 288 case "__FILE__": 289 case "__LINE__": 290 return true; 291 292 default: 293 return false; 294 } 295 }