LexBaan.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967
  1. // Scintilla source code edit control
  2. /** @file LexBaan.cxx
  3. ** Lexer for Baan.
  4. ** Based heavily on LexCPP.cxx
  5. **/
  6. // Copyright 2001- by Vamsi Potluru <vamsi@who.net> & Praveen Ambekar <ambekarpraveen@yahoo.com>
  7. // The License.txt file describes the conditions under which this software may be distributed.
  8. // C standard library
  9. #include <stdlib.h>
  10. #include <string.h>
  11. // C++ wrappers of C standard library
  12. #include <cassert>
  13. // C++ standard library
  14. #include <string>
  15. #include <map>
  16. // Scintilla headers
  17. // Non-platform-specific headers
  18. // include
  19. #include "ILexer.h"
  20. #include "Scintilla.h"
  21. #include "SciLexer.h"
  22. // lexlib
  23. #include "WordList.h"
  24. #include "LexAccessor.h"
  25. #include "StyleContext.h"
  26. #include "CharacterSet.h"
  27. #include "LexerModule.h"
  28. #include "OptionSet.h"
  29. # ifdef SCI_NAMESPACE
  30. using namespace Scintilla;
  31. # endif
  32. namespace {
  33. // Use an unnamed namespace to protect the functions and classes from name conflicts
  34. // Options used for LexerBaan
  35. struct OptionsBaan {
  36. bool fold;
  37. bool foldComment;
  38. bool foldPreprocessor;
  39. bool foldCompact;
  40. bool baanFoldSyntaxBased;
  41. bool baanFoldKeywordsBased;
  42. bool baanFoldSections;
  43. bool baanFoldInnerLevel;
  44. bool baanStylingWithinPreprocessor;
  45. OptionsBaan() {
  46. fold = false;
  47. foldComment = false;
  48. foldPreprocessor = false;
  49. foldCompact = false;
  50. baanFoldSyntaxBased = false;
  51. baanFoldKeywordsBased = false;
  52. baanFoldSections = false;
  53. baanFoldInnerLevel = false;
  54. baanStylingWithinPreprocessor = false;
  55. }
  56. };
  57. const char *const baanWordLists[] = {
  58. "Baan & BaanSQL Reserved Keywords ",
  59. "Baan Standard functions",
  60. "Baan Functions Abridged",
  61. "Baan Main Sections ",
  62. "Baan Sub Sections",
  63. "PreDefined Variables",
  64. "PreDefined Attributes",
  65. "Enumerates",
  66. 0,
  67. };
  68. struct OptionSetBaan : public OptionSet<OptionsBaan> {
  69. OptionSetBaan() {
  70. DefineProperty("fold", &OptionsBaan::fold);
  71. DefineProperty("fold.comment", &OptionsBaan::foldComment);
  72. DefineProperty("fold.preprocessor", &OptionsBaan::foldPreprocessor);
  73. DefineProperty("fold.compact", &OptionsBaan::foldCompact);
  74. DefineProperty("fold.baan.syntax.based", &OptionsBaan::baanFoldSyntaxBased,
  75. "Set this property to 0 to disable syntax based folding, which is folding based on '{' & '('.");
  76. DefineProperty("fold.baan.keywords.based", &OptionsBaan::baanFoldKeywordsBased,
  77. "Set this property to 0 to disable keywords based folding, which is folding based on "
  78. " for, if, on (case), repeat, select, while and fold ends based on endfor, endif, endcase, until, endselect, endwhile respectively."
  79. "Also folds declarations which are grouped together.");
  80. DefineProperty("fold.baan.sections", &OptionsBaan::baanFoldSections,
  81. "Set this property to 0 to disable folding of Main Sections as well as Sub Sections.");
  82. DefineProperty("fold.baan.inner.level", &OptionsBaan::baanFoldInnerLevel,
  83. "Set this property to 1 to enable folding of inner levels of select statements."
  84. "Disabled by default. case and if statements are also eligible" );
  85. DefineProperty("lexer.baan.styling.within.preprocessor", &OptionsBaan::baanStylingWithinPreprocessor,
  86. "For Baan code, determines whether all preprocessor code is styled in the "
  87. "preprocessor style (0, the default) or only from the initial # to the end "
  88. "of the command word(1).");
  89. DefineWordListSets(baanWordLists);
  90. }
  91. };
  92. static inline bool IsAWordChar(const int ch) {
  93. return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '$');
  94. }
  95. static inline bool IsAnOperator(int ch) {
  96. if (IsAlphaNumeric(ch))
  97. return false;
  98. if (ch == '#' || ch == '^' || ch == '&' || ch == '*' ||
  99. ch == '(' || ch == ')' || ch == '-' || ch == '+' ||
  100. ch == '=' || ch == '|' || ch == '{' || ch == '}' ||
  101. ch == '[' || ch == ']' || ch == ':' || ch == ';' ||
  102. ch == '<' || ch == '>' || ch == ',' || ch == '/' ||
  103. ch == '?' || ch == '!' || ch == '"' || ch == '~' ||
  104. ch == '\\')
  105. return true;
  106. return false;
  107. }
  108. static inline int IsAnyOtherIdentifier(char *s, int sLength) {
  109. /* IsAnyOtherIdentifier uses standard templates used in baan.
  110. The matching template is shown as comments just above the return condition.
  111. ^ - refers to any character [a-z].
  112. # - refers to any number [0-9].
  113. Other characters shown are compared as is.
  114. Tried implementing with Regex... it was too complicated for me.
  115. Any other implementation suggestion welcome.
  116. */
  117. switch (sLength) {
  118. case 8:
  119. if (isalpha(s[0]) && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && IsADigit(s[5]) && IsADigit(s[6]) && IsADigit(s[7])) {
  120. //^^^^^###
  121. return(SCE_BAAN_TABLEDEF);
  122. }
  123. break;
  124. case 9:
  125. if (s[0] == 't' && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && isalpha(s[5]) && IsADigit(s[6]) && IsADigit(s[7]) && IsADigit(s[8])) {
  126. //t^^^^^###
  127. return(SCE_BAAN_TABLEDEF);
  128. }
  129. else if (s[8] == '.' && isalpha(s[0]) && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && IsADigit(s[5]) && IsADigit(s[6]) && IsADigit(s[7])) {
  130. //^^^^^###.
  131. return(SCE_BAAN_TABLESQL);
  132. }
  133. break;
  134. case 13:
  135. if (s[8] == '.' && isalpha(s[0]) && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && IsADigit(s[5]) && IsADigit(s[6]) && IsADigit(s[7])) {
  136. //^^^^^###.****
  137. return(SCE_BAAN_TABLESQL);
  138. }
  139. else if (s[0] == 'r' && s[1] == 'c' && s[2] == 'd' && s[3] == '.' && s[4] == 't' && isalpha(s[5]) && isalpha(s[6]) && isalpha(s[7]) && isalpha(s[8]) && isalpha(s[9]) && IsADigit(s[10]) && IsADigit(s[11]) && IsADigit(s[12])) {
  140. //rcd.t^^^^^###
  141. return(SCE_BAAN_TABLEDEF);
  142. }
  143. break;
  144. case 14:
  145. case 15:
  146. if (s[8] == '.' && isalpha(s[0]) && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && IsADigit(s[5]) && IsADigit(s[6]) && IsADigit(s[7])) {
  147. if (s[13] != ':') {
  148. //^^^^^###.******
  149. return(SCE_BAAN_TABLESQL);
  150. }
  151. }
  152. break;
  153. case 16:
  154. case 17:
  155. if (s[8] == '.' && s[9] == '_' && s[10] == 'i' && s[11] == 'n' && s[12] == 'd' && s[13] == 'e' && s[14] == 'x' && IsADigit(s[15]) && isalpha(s[0]) && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && IsADigit(s[5]) && IsADigit(s[6]) && IsADigit(s[7])) {
  156. //^^^^^###._index##
  157. return(SCE_BAAN_TABLEDEF);
  158. }
  159. else if (s[8] == '.' && s[9] == '_' && s[10] == 'c' && s[11] == 'o' && s[12] == 'm' && s[13] == 'p' && s[14] == 'n' && s[15] == 'r' && isalpha(s[0]) && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && IsADigit(s[5]) && IsADigit(s[6]) && IsADigit(s[7])) {
  160. //^^^^^###._compnr
  161. return(SCE_BAAN_TABLEDEF);
  162. }
  163. break;
  164. default:
  165. break;
  166. }
  167. if (sLength > 14 && s[5] == '.' && s[6] == 'd' && s[7] == 'l' && s[8] == 'l' && s[13] == '.' && isalpha(s[0]) && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && IsADigit(s[9]) && IsADigit(s[10]) && IsADigit(s[11]) && IsADigit(s[12])) {
  168. //^^^^^.dll####.
  169. return(SCE_BAAN_FUNCTION);
  170. }
  171. else if (sLength > 15 && s[2] == 'i' && s[3] == 'n' && s[4] == 't' && s[5] == '.' && s[6] == 'd' && s[7] == 'l' && s[8] == 'l' && isalpha(s[0]) && isalpha(s[1]) && isalpha(s[9]) && isalpha(s[10]) && isalpha(s[11]) && isalpha(s[12]) && isalpha(s[13])) {
  172. //^^int.dll^^^^^.
  173. return(SCE_BAAN_FUNCTION);
  174. }
  175. else if (sLength > 11 && s[0] == 'i' && s[10] == '.' && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && isalpha(s[5]) && IsADigit(s[6]) && IsADigit(s[7]) && IsADigit(s[8]) && IsADigit(s[9])) {
  176. //i^^^^^####.
  177. return(SCE_BAAN_FUNCTION);
  178. }
  179. return(SCE_BAAN_DEFAULT);
  180. }
  181. static bool IsCommentLine(Sci_Position line, LexAccessor &styler) {
  182. Sci_Position pos = styler.LineStart(line);
  183. Sci_Position eol_pos = styler.LineStart(line + 1) - 1;
  184. for (Sci_Position i = pos; i < eol_pos; i++) {
  185. char ch = styler[i];
  186. int style = styler.StyleAt(i);
  187. if (ch == '|' && style == SCE_BAAN_COMMENT)
  188. return true;
  189. else if (!IsASpaceOrTab(ch))
  190. return false;
  191. }
  192. return false;
  193. }
  194. static bool IsPreProcLine(Sci_Position line, LexAccessor &styler) {
  195. Sci_Position pos = styler.LineStart(line);
  196. Sci_Position eol_pos = styler.LineStart(line + 1) - 1;
  197. for (Sci_Position i = pos; i < eol_pos; i++) {
  198. char ch = styler[i];
  199. int style = styler.StyleAt(i);
  200. if (ch == '#' && style == SCE_BAAN_PREPROCESSOR) {
  201. if (styler.Match(i, "#elif") || styler.Match(i, "#else") || styler.Match(i, "#endif")
  202. || styler.Match(i, "#if") || styler.Match(i, "#ifdef") || styler.Match(i, "#ifndef"))
  203. // Above PreProcessors has a seperate fold mechanism.
  204. return false;
  205. else
  206. return true;
  207. }
  208. else if (ch == '^')
  209. return true;
  210. else if (!IsASpaceOrTab(ch))
  211. return false;
  212. }
  213. return false;
  214. }
  215. static int mainOrSubSectionLine(Sci_Position line, LexAccessor &styler) {
  216. Sci_Position pos = styler.LineStart(line);
  217. Sci_Position eol_pos = styler.LineStart(line + 1) - 1;
  218. for (Sci_Position i = pos; i < eol_pos; i++) {
  219. char ch = styler[i];
  220. int style = styler.StyleAt(i);
  221. if (style == SCE_BAAN_WORD5 || style == SCE_BAAN_WORD4)
  222. return style;
  223. else if (IsASpaceOrTab(ch))
  224. continue;
  225. else
  226. break;
  227. }
  228. return 0;
  229. }
  230. static bool priorSectionIsSubSection(Sci_Position line, LexAccessor &styler){
  231. while (line > 0) {
  232. Sci_Position pos = styler.LineStart(line);
  233. Sci_Position eol_pos = styler.LineStart(line + 1) - 1;
  234. for (Sci_Position i = pos; i < eol_pos; i++) {
  235. char ch = styler[i];
  236. int style = styler.StyleAt(i);
  237. if (style == SCE_BAAN_WORD4)
  238. return true;
  239. else if (style == SCE_BAAN_WORD5)
  240. return false;
  241. else if (IsASpaceOrTab(ch))
  242. continue;
  243. else
  244. break;
  245. }
  246. line--;
  247. }
  248. return false;
  249. }
  250. static bool nextSectionIsSubSection(Sci_Position line, LexAccessor &styler) {
  251. while (line > 0) {
  252. Sci_Position pos = styler.LineStart(line);
  253. Sci_Position eol_pos = styler.LineStart(line + 1) - 1;
  254. for (Sci_Position i = pos; i < eol_pos; i++) {
  255. char ch = styler[i];
  256. int style = styler.StyleAt(i);
  257. if (style == SCE_BAAN_WORD4)
  258. return true;
  259. else if (style == SCE_BAAN_WORD5)
  260. return false;
  261. else if (IsASpaceOrTab(ch))
  262. continue;
  263. else
  264. break;
  265. }
  266. line++;
  267. }
  268. return false;
  269. }
  270. static bool IsDeclarationLine(Sci_Position line, LexAccessor &styler) {
  271. Sci_Position pos = styler.LineStart(line);
  272. Sci_Position eol_pos = styler.LineStart(line + 1) - 1;
  273. for (Sci_Position i = pos; i < eol_pos; i++) {
  274. char ch = styler[i];
  275. int style = styler.StyleAt(i);
  276. if (style == SCE_BAAN_WORD) {
  277. if (styler.Match(i, "table") || styler.Match(i, "extern") || styler.Match(i, "long")
  278. || styler.Match(i, "double") || styler.Match(i, "boolean") || styler.Match(i, "string")
  279. || styler.Match(i, "domain")) {
  280. for (Sci_Position j = eol_pos; j > pos; j--) {
  281. int styleFromEnd = styler.StyleAt(j);
  282. if (styleFromEnd == SCE_BAAN_COMMENT)
  283. continue;
  284. else if (IsASpace(styler[j]))
  285. continue;
  286. else if (styler[j] != ',')
  287. //Above conditions ensures, Declaration is not part of any function parameters.
  288. return true;
  289. else
  290. return false;
  291. }
  292. }
  293. else
  294. return false;
  295. }
  296. else if (!IsASpaceOrTab(ch))
  297. return false;
  298. }
  299. return false;
  300. }
  301. static bool IsInnerLevelFold(Sci_Position line, LexAccessor &styler) {
  302. Sci_Position pos = styler.LineStart(line);
  303. Sci_Position eol_pos = styler.LineStart(line + 1) - 1;
  304. for (Sci_Position i = pos; i < eol_pos; i++) {
  305. char ch = styler[i];
  306. int style = styler.StyleAt(i);
  307. if (style == SCE_BAAN_WORD && (styler.Match(i, "else" ) || styler.Match(i, "case")
  308. || styler.Match(i, "default") || styler.Match(i, "selectdo") || styler.Match(i, "selecteos")
  309. || styler.Match(i, "selectempty") || styler.Match(i, "selecterror")))
  310. return true;
  311. else if (IsASpaceOrTab(ch))
  312. continue;
  313. else
  314. return false;
  315. }
  316. return false;
  317. }
  318. static inline bool wordInArray(const std::string& value, std::string *array, int length)
  319. {
  320. for (int i = 0; i < length; i++)
  321. {
  322. if (value == array[i])
  323. {
  324. return true;
  325. }
  326. }
  327. return false;
  328. }
  329. class WordListAbridged : public WordList {
  330. public:
  331. WordListAbridged() {
  332. kwAbridged = false;
  333. kwHasSection = false;
  334. };
  335. ~WordListAbridged() {
  336. Clear();
  337. };
  338. bool kwAbridged;
  339. bool kwHasSection;
  340. bool Contains(const char *s) {
  341. return kwAbridged ? InListAbridged(s, '~') : InList(s);
  342. };
  343. };
  344. }
  345. class LexerBaan : public ILexer {
  346. WordListAbridged keywords;
  347. WordListAbridged keywords2;
  348. WordListAbridged keywords3;
  349. WordListAbridged keywords4;
  350. WordListAbridged keywords5;
  351. WordListAbridged keywords6;
  352. WordListAbridged keywords7;
  353. WordListAbridged keywords8;
  354. WordListAbridged keywords9;
  355. OptionsBaan options;
  356. OptionSetBaan osBaan;
  357. public:
  358. LexerBaan() {
  359. }
  360. virtual ~LexerBaan() {
  361. }
  362. int SCI_METHOD Version() const {
  363. return lvOriginal;
  364. }
  365. void SCI_METHOD Release() {
  366. delete this;
  367. }
  368. const char * SCI_METHOD PropertyNames() {
  369. return osBaan.PropertyNames();
  370. }
  371. int SCI_METHOD PropertyType(const char * name) {
  372. return osBaan.PropertyType(name);
  373. }
  374. const char * SCI_METHOD DescribeProperty(const char * name) {
  375. return osBaan.DescribeProperty(name);
  376. }
  377. Sci_Position SCI_METHOD PropertySet(const char *key, const char *val);
  378. const char * SCI_METHOD DescribeWordListSets() {
  379. return osBaan.DescribeWordListSets();
  380. }
  381. Sci_Position SCI_METHOD WordListSet(int n, const char *wl);
  382. void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess);
  383. void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess);
  384. void * SCI_METHOD PrivateCall(int, void *) {
  385. return NULL;
  386. }
  387. static ILexer * LexerFactoryBaan() {
  388. return new LexerBaan();
  389. }
  390. };
  391. Sci_Position SCI_METHOD LexerBaan::PropertySet(const char *key, const char *val) {
  392. if (osBaan.PropertySet(&options, key, val)) {
  393. return 0;
  394. }
  395. return -1;
  396. }
  397. Sci_Position SCI_METHOD LexerBaan::WordListSet(int n, const char *wl) {
  398. WordListAbridged *WordListAbridgedN = 0;
  399. switch (n) {
  400. case 0:
  401. WordListAbridgedN = &keywords;
  402. break;
  403. case 1:
  404. WordListAbridgedN = &keywords2;
  405. break;
  406. case 2:
  407. WordListAbridgedN = &keywords3;
  408. break;
  409. case 3:
  410. WordListAbridgedN = &keywords4;
  411. break;
  412. case 4:
  413. WordListAbridgedN = &keywords5;
  414. break;
  415. case 5:
  416. WordListAbridgedN = &keywords6;
  417. break;
  418. case 6:
  419. WordListAbridgedN = &keywords7;
  420. break;
  421. case 7:
  422. WordListAbridgedN = &keywords8;
  423. break;
  424. case 8:
  425. WordListAbridgedN = &keywords9;
  426. break;
  427. }
  428. Sci_Position firstModification = -1;
  429. if (WordListAbridgedN) {
  430. WordListAbridged wlNew;
  431. wlNew.Set(wl);
  432. if (*WordListAbridgedN != wlNew) {
  433. WordListAbridgedN->Set(wl);
  434. WordListAbridgedN->kwAbridged = strchr(wl, '~') != NULL;
  435. WordListAbridgedN->kwHasSection = strchr(wl, ':') != NULL;
  436. firstModification = 0;
  437. }
  438. }
  439. return firstModification;
  440. }
  441. void SCI_METHOD LexerBaan::Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) {
  442. if (initStyle == SCE_BAAN_STRINGEOL) // Does not leak onto next line
  443. initStyle = SCE_BAAN_DEFAULT;
  444. int visibleChars = 0;
  445. bool lineHasDomain = false;
  446. bool lineHasFunction = false;
  447. bool lineHasPreProc = false;
  448. bool lineIgnoreString = false;
  449. bool lineHasDefines = false;
  450. char word[1000];
  451. int wordlen = 0;
  452. std::string preProcessorTags[11] = { "#define", "#elif", "#else", "#endif",
  453. "#ident", "#if", "#ifdef", "#ifndef",
  454. "#include", "#pragma", "#undef" };
  455. LexAccessor styler(pAccess);
  456. StyleContext sc(startPos, length, initStyle, styler);
  457. for (; sc.More(); sc.Forward()) {
  458. // Determine if the current state should terminate.
  459. switch (sc.state) {
  460. case SCE_BAAN_OPERATOR:
  461. sc.SetState(SCE_BAAN_DEFAULT);
  462. break;
  463. case SCE_BAAN_NUMBER:
  464. if (!IsAWordChar(sc.ch)) {
  465. sc.SetState(SCE_BAAN_DEFAULT);
  466. }
  467. break;
  468. case SCE_BAAN_IDENTIFIER:
  469. if (!IsAWordChar(sc.ch)) {
  470. char s[1000];
  471. char s1[1000];
  472. sc.GetCurrentLowered(s, sizeof(s));
  473. if (sc.ch == ':') {
  474. memcpy(s1, s, sizeof(s));
  475. s1[sc.LengthCurrent()] = sc.ch;
  476. s1[sc.LengthCurrent() + 1] = '\0';
  477. }
  478. if ((keywords.kwHasSection && (sc.ch == ':')) ? keywords.Contains(s1) : keywords.Contains(s)) {
  479. sc.ChangeState(SCE_BAAN_WORD);
  480. if (0 == strcmp(s, "domain")) {
  481. lineHasDomain = true;
  482. }
  483. else if (0 == strcmp(s, "function")) {
  484. lineHasFunction = true;
  485. }
  486. }
  487. else if (lineHasDomain) {
  488. sc.ChangeState(SCE_BAAN_DOMDEF);
  489. lineHasDomain = false;
  490. }
  491. else if (lineHasFunction) {
  492. sc.ChangeState(SCE_BAAN_FUNCDEF);
  493. lineHasFunction = false;
  494. }
  495. else if ((keywords2.kwHasSection && (sc.ch == ':')) ? keywords2.Contains(s1) : keywords2.Contains(s)) {
  496. sc.ChangeState(SCE_BAAN_WORD2);
  497. }
  498. else if ((keywords3.kwHasSection && (sc.ch == ':')) ? keywords3.Contains(s1) : keywords3.Contains(s)) {
  499. sc.ChangeState(SCE_BAAN_WORD3);
  500. }
  501. else if ((keywords4.kwHasSection && (sc.ch == ':')) ? keywords4.Contains(s1) : keywords4.Contains(s)) {
  502. sc.ChangeState(SCE_BAAN_WORD4);
  503. }
  504. else if ((keywords5.kwHasSection && (sc.ch == ':')) ? keywords5.Contains(s1) : keywords5.Contains(s)) {
  505. sc.ChangeState(SCE_BAAN_WORD5);
  506. }
  507. else if ((keywords6.kwHasSection && (sc.ch == ':')) ? keywords6.Contains(s1) : keywords6.Contains(s)) {
  508. sc.ChangeState(SCE_BAAN_WORD6);
  509. }
  510. else if ((keywords7.kwHasSection && (sc.ch == ':')) ? keywords7.Contains(s1) : keywords7.Contains(s)) {
  511. sc.ChangeState(SCE_BAAN_WORD7);
  512. }
  513. else if ((keywords8.kwHasSection && (sc.ch == ':')) ? keywords8.Contains(s1) : keywords8.Contains(s)) {
  514. sc.ChangeState(SCE_BAAN_WORD8);
  515. }
  516. else if ((keywords9.kwHasSection && (sc.ch == ':')) ? keywords9.Contains(s1) : keywords9.Contains(s)) {
  517. sc.ChangeState(SCE_BAAN_WORD9);
  518. }
  519. else if (lineHasPreProc) {
  520. sc.ChangeState(SCE_BAAN_OBJECTDEF);
  521. lineHasPreProc = false;
  522. }
  523. else if (lineHasDefines) {
  524. sc.ChangeState(SCE_BAAN_DEFINEDEF);
  525. lineHasDefines = false;
  526. }
  527. else {
  528. int state = IsAnyOtherIdentifier(s, sc.LengthCurrent());
  529. if (state > 0) {
  530. sc.ChangeState(state);
  531. }
  532. }
  533. sc.SetState(SCE_BAAN_DEFAULT);
  534. }
  535. break;
  536. case SCE_BAAN_PREPROCESSOR:
  537. if (options.baanStylingWithinPreprocessor) {
  538. if (IsASpace(sc.ch) || IsAnOperator(sc.ch)) {
  539. sc.SetState(SCE_BAAN_DEFAULT);
  540. }
  541. }
  542. else {
  543. if (sc.atLineEnd && (sc.chNext != '^')) {
  544. sc.SetState(SCE_BAAN_DEFAULT);
  545. }
  546. }
  547. break;
  548. case SCE_BAAN_COMMENT:
  549. if (sc.atLineEnd) {
  550. sc.SetState(SCE_BAAN_DEFAULT);
  551. }
  552. break;
  553. case SCE_BAAN_COMMENTDOC:
  554. if (sc.MatchIgnoreCase("enddllusage")) {
  555. for (unsigned int i = 0; i < 10; i++) {
  556. sc.Forward();
  557. }
  558. sc.ForwardSetState(SCE_BAAN_DEFAULT);
  559. }
  560. else if (sc.MatchIgnoreCase("endfunctionusage")) {
  561. for (unsigned int i = 0; i < 15; i++) {
  562. sc.Forward();
  563. }
  564. sc.ForwardSetState(SCE_BAAN_DEFAULT);
  565. }
  566. break;
  567. case SCE_BAAN_STRING:
  568. if (sc.ch == '\"') {
  569. sc.ForwardSetState(SCE_BAAN_DEFAULT);
  570. }
  571. else if ((sc.atLineEnd) && (sc.chNext != '^')) {
  572. sc.ChangeState(SCE_BAAN_STRINGEOL);
  573. sc.ForwardSetState(SCE_BAAN_DEFAULT);
  574. visibleChars = 0;
  575. }
  576. break;
  577. }
  578. // Determine if a new state should be entered.
  579. if (sc.state == SCE_BAAN_DEFAULT) {
  580. if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
  581. sc.SetState(SCE_BAAN_NUMBER);
  582. }
  583. else if (sc.MatchIgnoreCase("dllusage") || sc.MatchIgnoreCase("functionusage")) {
  584. sc.SetState(SCE_BAAN_COMMENTDOC);
  585. do {
  586. sc.Forward();
  587. } while ((!sc.atLineEnd) && sc.More());
  588. }
  589. else if (iswordstart(sc.ch)) {
  590. sc.SetState(SCE_BAAN_IDENTIFIER);
  591. }
  592. else if (sc.Match('|')) {
  593. sc.SetState(SCE_BAAN_COMMENT);
  594. }
  595. else if (sc.ch == '\"' && !(lineIgnoreString)) {
  596. sc.SetState(SCE_BAAN_STRING);
  597. }
  598. else if (sc.ch == '#' && visibleChars == 0) {
  599. // Preprocessor commands are alone on their line
  600. sc.SetState(SCE_BAAN_PREPROCESSOR);
  601. word[0] = '\0';
  602. wordlen = 0;
  603. while (sc.More() && !(IsASpace(sc.chNext) || IsAnOperator(sc.chNext))) {
  604. sc.Forward();
  605. wordlen++;
  606. }
  607. sc.GetCurrentLowered(word, sizeof(word));
  608. if (!sc.atLineEnd) {
  609. word[wordlen++] = sc.ch;
  610. word[wordlen++] = '\0';
  611. }
  612. if (!wordInArray(word, preProcessorTags, 11))
  613. // Colorise only preprocessor built in Baan.
  614. sc.ChangeState(SCE_BAAN_IDENTIFIER);
  615. if (strcmp(word, "#pragma") == 0 || strcmp(word, "#include") == 0) {
  616. lineHasPreProc = true;
  617. lineIgnoreString = true;
  618. }
  619. else if (strcmp(word, "#define") == 0 || strcmp(word, "#undef") == 0 ||
  620. strcmp(word, "#ifdef") == 0 || strcmp(word, "#if") == 0 || strcmp(word, "#ifndef") == 0) {
  621. lineHasDefines = true;
  622. lineIgnoreString = false;
  623. }
  624. }
  625. else if (IsAnOperator(static_cast<char>(sc.ch))) {
  626. sc.SetState(SCE_BAAN_OPERATOR);
  627. }
  628. }
  629. if (sc.atLineEnd) {
  630. // Reset states to begining of colourise so no surprises
  631. // if different sets of lines lexed.
  632. visibleChars = 0;
  633. lineHasDomain = false;
  634. lineHasFunction = false;
  635. lineHasPreProc = false;
  636. lineIgnoreString = false;
  637. lineHasDefines = false;
  638. }
  639. if (!IsASpace(sc.ch)) {
  640. visibleChars++;
  641. }
  642. }
  643. sc.Complete();
  644. }
  645. void SCI_METHOD LexerBaan::Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) {
  646. if (!options.fold)
  647. return;
  648. char word[100];
  649. int wordlen = 0;
  650. bool foldStart = true;
  651. bool foldNextSelect = true;
  652. bool afterFunctionSection = false;
  653. bool beforeDeclarationSection = false;
  654. int currLineStyle = 0;
  655. int nextLineStyle = 0;
  656. std::string startTags[6] = { "for", "if", "on", "repeat", "select", "while" };
  657. std::string endTags[6] = { "endcase", "endfor", "endif", "endselect", "endwhile", "until" };
  658. std::string selectCloseTags[5] = { "selectdo", "selecteos", "selectempty", "selecterror", "endselect" };
  659. LexAccessor styler(pAccess);
  660. Sci_PositionU endPos = startPos + length;
  661. int visibleChars = 0;
  662. Sci_Position lineCurrent = styler.GetLine(startPos);
  663. // Backtrack to previous line in case need to fix its fold status
  664. if (startPos > 0) {
  665. if (lineCurrent > 0) {
  666. lineCurrent--;
  667. startPos = styler.LineStart(lineCurrent);
  668. }
  669. }
  670. int levelPrev = SC_FOLDLEVELBASE;
  671. if (lineCurrent > 0)
  672. levelPrev = styler.LevelAt(lineCurrent - 1) >> 16;
  673. int levelCurrent = levelPrev;
  674. char chNext = styler[startPos];
  675. int style = initStyle;
  676. int styleNext = styler.StyleAt(startPos);
  677. for (Sci_PositionU i = startPos; i < endPos; i++) {
  678. char ch = chNext;
  679. chNext = styler.SafeGetCharAt(i + 1);
  680. style = styleNext;
  681. styleNext = styler.StyleAt(i + 1);
  682. int stylePrev = (i) ? styler.StyleAt(i - 1) : SCE_BAAN_DEFAULT;
  683. bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
  684. // Comment folding
  685. if (options.foldComment && style == SCE_BAAN_COMMENTDOC) {
  686. if (style != stylePrev) {
  687. levelCurrent++;
  688. }
  689. else if (style != styleNext) {
  690. levelCurrent--;
  691. }
  692. }
  693. if (options.foldComment && atEOL && IsCommentLine(lineCurrent, styler)) {
  694. if (!IsCommentLine(lineCurrent - 1, styler)
  695. && IsCommentLine(lineCurrent + 1, styler))
  696. levelCurrent++;
  697. else if (IsCommentLine(lineCurrent - 1, styler)
  698. && !IsCommentLine(lineCurrent + 1, styler))
  699. levelCurrent--;
  700. }
  701. // PreProcessor Folding
  702. if (options.foldPreprocessor) {
  703. if (atEOL && IsPreProcLine(lineCurrent, styler)) {
  704. if (!IsPreProcLine(lineCurrent - 1, styler)
  705. && IsPreProcLine(lineCurrent + 1, styler))
  706. levelCurrent++;
  707. else if (IsPreProcLine(lineCurrent - 1, styler)
  708. && !IsPreProcLine(lineCurrent + 1, styler))
  709. levelCurrent--;
  710. }
  711. else if (style == SCE_BAAN_PREPROCESSOR) {
  712. // folds #ifdef/#if/#ifndef - they are not part of the IsPreProcLine folding.
  713. if (ch == '#') {
  714. if (styler.Match(i, "#ifdef") || styler.Match(i, "#if") || styler.Match(i, "#ifndef"))
  715. levelCurrent++;
  716. else if (styler.Match(i, "#endif"))
  717. levelCurrent--;
  718. }
  719. }
  720. }
  721. //Syntax Folding
  722. if (options.baanFoldSyntaxBased && (style == SCE_BAAN_OPERATOR)) {
  723. if (ch == '{' || ch == '(') {
  724. levelCurrent++;
  725. }
  726. else if (ch == '}' || ch == ')') {
  727. levelCurrent--;
  728. }
  729. }
  730. //Keywords Folding
  731. if (options.baanFoldKeywordsBased) {
  732. if (atEOL && IsDeclarationLine(lineCurrent, styler)) {
  733. if (!IsDeclarationLine(lineCurrent - 1, styler)
  734. && IsDeclarationLine(lineCurrent + 1, styler))
  735. levelCurrent++;
  736. else if (IsDeclarationLine(lineCurrent - 1, styler)
  737. && !IsDeclarationLine(lineCurrent + 1, styler))
  738. levelCurrent--;
  739. }
  740. else if (style == SCE_BAAN_WORD) {
  741. word[wordlen++] = static_cast<char>(MakeLowerCase(ch));
  742. if (wordlen == 100) { // prevent overflow
  743. word[0] = '\0';
  744. wordlen = 1;
  745. }
  746. if (styleNext != SCE_BAAN_WORD) {
  747. word[wordlen] = '\0';
  748. wordlen = 0;
  749. if (strcmp(word, "for") == 0) {
  750. Sci_PositionU j = i + 1;
  751. while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) {
  752. j++;
  753. }
  754. if (styler.Match(j, "update")) {
  755. // Means this is a "for update" used by Select which is already folded.
  756. foldStart = false;
  757. }
  758. }
  759. else if (strcmp(word, "on") == 0) {
  760. Sci_PositionU j = i + 1;
  761. while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) {
  762. j++;
  763. }
  764. if (!styler.Match(j, "case")) {
  765. // Means this is not a "on Case" statement... could be "on" used by index.
  766. foldStart = false;
  767. }
  768. }
  769. else if (strcmp(word, "select") == 0) {
  770. if (foldNextSelect) {
  771. // Next Selects are sub-clause till reach of selectCloseTags[] array.
  772. foldNextSelect = false;
  773. foldStart = true;
  774. }
  775. else {
  776. foldNextSelect = false;
  777. foldStart = false;
  778. }
  779. }
  780. else if (wordInArray(word, selectCloseTags, 5)) {
  781. // select clause ends, next select clause can be folded.
  782. foldNextSelect = true;
  783. foldStart = true;
  784. }
  785. else {
  786. foldStart = true;
  787. }
  788. if (foldStart) {
  789. if (wordInArray(word, startTags, 6)) {
  790. levelCurrent++;
  791. }
  792. else if (wordInArray(word, endTags, 6)) {
  793. levelCurrent--;
  794. }
  795. }
  796. }
  797. }
  798. }
  799. // Fold inner level of if/select/case statements
  800. if (options.baanFoldInnerLevel && atEOL) {
  801. bool currLineInnerLevel = IsInnerLevelFold(lineCurrent, styler);
  802. bool nextLineInnerLevel = IsInnerLevelFold(lineCurrent + 1, styler);
  803. if (currLineInnerLevel && currLineInnerLevel != nextLineInnerLevel) {
  804. levelCurrent++;
  805. }
  806. else if (nextLineInnerLevel && nextLineInnerLevel != currLineInnerLevel) {
  807. levelCurrent--;
  808. }
  809. }
  810. // Section Foldings.
  811. // One way of implementing Section Foldings, as there is no END markings of sections.
  812. // first section ends on the previous line of next section.
  813. // Re-written whole folding to accomodate this.
  814. if (options.baanFoldSections && atEOL) {
  815. currLineStyle = mainOrSubSectionLine(lineCurrent, styler);
  816. nextLineStyle = mainOrSubSectionLine(lineCurrent + 1, styler);
  817. if (currLineStyle != 0 && currLineStyle != nextLineStyle) {
  818. if (levelCurrent < levelPrev)
  819. --levelPrev;
  820. for (Sci_Position j = styler.LineStart(lineCurrent); j < styler.LineStart(lineCurrent + 1) - 1; j++) {
  821. if (IsASpaceOrTab(styler[j]))
  822. continue;
  823. else if (styler.StyleAt(j) == SCE_BAAN_WORD5) {
  824. if (styler.Match(j, "functions:")) {
  825. // Means functions: is the end of MainSections.
  826. // Nothing to fold after this.
  827. afterFunctionSection = true;
  828. break;
  829. }
  830. else {
  831. afterFunctionSection = false;
  832. break;
  833. }
  834. }
  835. else {
  836. afterFunctionSection = false;
  837. break;
  838. }
  839. }
  840. if (!afterFunctionSection)
  841. levelCurrent++;
  842. }
  843. else if (nextLineStyle != 0 && currLineStyle != nextLineStyle
  844. && (priorSectionIsSubSection(lineCurrent -1 ,styler)
  845. || !nextSectionIsSubSection(lineCurrent + 1, styler))) {
  846. for (Sci_Position j = styler.LineStart(lineCurrent + 1); j < styler.LineStart(lineCurrent + 1 + 1) - 1; j++) {
  847. if (IsASpaceOrTab(styler[j]))
  848. continue;
  849. else if (styler.StyleAt(j) == SCE_BAAN_WORD5) {
  850. if (styler.Match(j, "declaration:")) {
  851. // Means declaration: is the start of MainSections.
  852. // Nothing to fold before this.
  853. beforeDeclarationSection = true;
  854. break;
  855. }
  856. else {
  857. beforeDeclarationSection = false;
  858. break;
  859. }
  860. }
  861. else {
  862. beforeDeclarationSection = false;
  863. break;
  864. }
  865. }
  866. if (!beforeDeclarationSection) {
  867. levelCurrent--;
  868. if (nextLineStyle == SCE_BAAN_WORD5 && priorSectionIsSubSection(lineCurrent-1, styler))
  869. // next levelCurrent--; is to unfold previous subsection fold.
  870. // On reaching the next main section, the previous main as well sub section ends.
  871. levelCurrent--;
  872. }
  873. }
  874. }
  875. if (atEOL) {
  876. int lev = levelPrev;
  877. lev |= levelCurrent << 16;
  878. if (visibleChars == 0 && options.foldCompact)
  879. lev |= SC_FOLDLEVELWHITEFLAG;
  880. if ((levelCurrent > levelPrev) && (visibleChars > 0))
  881. lev |= SC_FOLDLEVELHEADERFLAG;
  882. if (lev != styler.LevelAt(lineCurrent)) {
  883. styler.SetLevel(lineCurrent, lev);
  884. }
  885. lineCurrent++;
  886. levelPrev = levelCurrent;
  887. visibleChars = 0;
  888. }
  889. if (!isspacechar(ch))
  890. visibleChars++;
  891. }
  892. int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
  893. styler.SetLevel(lineCurrent, levelPrev | flagsNext);
  894. }
  895. LexerModule lmBaan(SCLEX_BAAN, LexerBaan::LexerFactoryBaan, "baan", baanWordLists);