/mks-svn4458/qscintilla/QScintilla-gpl-snapshot/lexers/LexModula.cpp

# · C++ · 743 lines · 679 code · 53 blank · 11 comment · 233 complexity · bfd1588a7717c84f2a56ba95e87a0bcd MD5 · raw file

  1. // -*- coding: utf-8 -*-
  2. // Scintilla source code edit control
  3. /**
  4. * @file LexModula.cxx
  5. * @author Dariusz "DKnoto" Knoci?„ski
  6. * @date 2011/02/03
  7. * @brief Lexer for Modula-2/3 documents.
  8. */
  9. // The License.txt file describes the conditions under which this software may
  10. // be distributed.
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <stdio.h>
  14. #include <stdarg.h>
  15. #include <assert.h>
  16. #include <ctype.h>
  17. #include "ILexer.h"
  18. #include "Scintilla.h"
  19. #include "SciLexer.h"
  20. #include "PropSetSimple.h"
  21. #include "WordList.h"
  22. #include "LexAccessor.h"
  23. #include "Accessor.h"
  24. #include "StyleContext.h"
  25. #include "CharacterSet.h"
  26. #include "LexerModule.h"
  27. #ifdef SCI_NAMESPACE
  28. using namespace Scintilla;
  29. #endif
  30. #ifdef DEBUG_LEX_MODULA
  31. #define DEBUG_STATE( p, c )\
  32. fprintf( stderr, "Unknown state: currentPos = %d, char = '%c'\n", p, c );
  33. #else
  34. #define DEBUG_STATE( p, c )
  35. #endif
  36. static inline bool IsDigitOfBase( unsigned ch, unsigned base ) {
  37. if( ch < '0' || ch > 'f' ) return false;
  38. if( base <= 10 ) {
  39. if( ch >= ( '0' + base ) ) return false;
  40. } else {
  41. if( ch > '9' ) {
  42. unsigned nb = base - 10;
  43. if( ( ch < 'A' ) || ( ch >= ( 'A' + nb ) ) ) {
  44. if( ( ch < 'a' ) || ( ch >= ( 'a' + nb ) ) ) {
  45. return false;
  46. }
  47. }
  48. }
  49. }
  50. return true;
  51. }
  52. static inline unsigned IsOperator( StyleContext & sc, WordList & op ) {
  53. int i;
  54. char s[3];
  55. s[0] = sc.ch;
  56. s[1] = sc.chNext;
  57. s[2] = 0;
  58. for( i = 0; i < op.len; i++ ) {
  59. if( ( strlen( op.words[i] ) == 2 ) &&
  60. ( s[0] == op.words[i][0] && s[1] == op.words[i][1] ) ) {
  61. return 2;
  62. }
  63. }
  64. s[1] = 0;
  65. for( i = 0; i < op.len; i++ ) {
  66. if( ( strlen( op.words[i] ) == 1 ) &&
  67. ( s[0] == op.words[i][0] ) ) {
  68. return 1;
  69. }
  70. }
  71. return 0;
  72. }
  73. static inline bool IsEOL( Accessor &styler, unsigned curPos ) {
  74. unsigned ch = styler.SafeGetCharAt( curPos );
  75. if( ( ch == '\r' && styler.SafeGetCharAt( curPos + 1 ) == '\n' ) ||
  76. ( ch == '\n' ) ) {
  77. return true;
  78. }
  79. return false;
  80. }
  81. static inline bool checkStatement(
  82. Accessor &styler,
  83. int &curPos,
  84. const char *stt, bool spaceAfter = true ) {
  85. int len = static_cast<int>(strlen( stt ));
  86. int i;
  87. for( i = 0; i < len; i++ ) {
  88. if( styler.SafeGetCharAt( curPos + i ) != stt[i] ) {
  89. return false;
  90. }
  91. }
  92. if( spaceAfter ) {
  93. if( ! isspace( styler.SafeGetCharAt( curPos + i ) ) ) {
  94. return false;
  95. }
  96. }
  97. curPos += ( len - 1 );
  98. return true;
  99. }
  100. static inline bool checkEndSemicolon(
  101. Accessor &styler,
  102. int &curPos, int endPos )
  103. {
  104. const char *stt = "END";
  105. int len = static_cast<int>(strlen( stt ));
  106. int i;
  107. for( i = 0; i < len; i++ ) {
  108. if( styler.SafeGetCharAt( curPos + i ) != stt[i] ) {
  109. return false;
  110. }
  111. }
  112. while( isspace( styler.SafeGetCharAt( curPos + i ) ) ) {
  113. i++;
  114. if( ( curPos + i ) >= endPos ) return false;
  115. }
  116. if( styler.SafeGetCharAt( curPos + i ) != ';' ) {
  117. return false;
  118. }
  119. curPos += ( i - 1 );
  120. return true;
  121. }
  122. static inline bool checkKeyIdentOper(
  123. Accessor &styler,
  124. int &curPos, int endPos,
  125. const char *stt, const char etk ) {
  126. int newPos = curPos;
  127. if( ! checkStatement( styler, newPos, stt ) )
  128. return false;
  129. newPos++;
  130. if( newPos >= endPos )
  131. return false;
  132. if( ! isspace( styler.SafeGetCharAt( newPos ) ) )
  133. return false;
  134. newPos++;
  135. if( newPos >= endPos )
  136. return false;
  137. while( isspace( styler.SafeGetCharAt( newPos ) ) ) {
  138. newPos++;
  139. if( newPos >= endPos )
  140. return false;
  141. }
  142. if( ! isalpha( styler.SafeGetCharAt( newPos ) ) )
  143. return false;
  144. newPos++;
  145. if( newPos >= endPos )
  146. return false;
  147. char ch;
  148. ch = styler.SafeGetCharAt( newPos );
  149. while( isalpha( ch ) || isdigit( ch ) || ch == '_' ) {
  150. newPos++;
  151. if( newPos >= endPos ) return false;
  152. ch = styler.SafeGetCharAt( newPos );
  153. }
  154. while( isspace( styler.SafeGetCharAt( newPos ) ) ) {
  155. newPos++;
  156. if( newPos >= endPos ) return false;
  157. }
  158. if( styler.SafeGetCharAt( newPos ) != etk )
  159. return false;
  160. curPos = newPos;
  161. return true;
  162. }
  163. static void FoldModulaDoc( unsigned int startPos,
  164. int length,
  165. int , WordList *[],
  166. Accessor &styler)
  167. {
  168. int curLine = styler.GetLine(startPos);
  169. int curLevel = SC_FOLDLEVELBASE;
  170. int endPos = startPos + length;
  171. if( curLine > 0 )
  172. curLevel = styler.LevelAt( curLine - 1 ) >> 16;
  173. int curPos = startPos;
  174. int style = styler.StyleAt( curPos );
  175. int visChars = 0;
  176. int nextLevel = curLevel;
  177. while( curPos < endPos ) {
  178. if( ! isspace( styler.SafeGetCharAt( curPos ) ) ) visChars++;
  179. switch( style ) {
  180. case SCE_MODULA_COMMENT:
  181. if( checkStatement( styler, curPos, "(*" ) )
  182. nextLevel++;
  183. else
  184. if( checkStatement( styler, curPos, "*)" ) )
  185. nextLevel--;
  186. break;
  187. case SCE_MODULA_DOXYCOMM:
  188. if( checkStatement( styler, curPos, "(**", false ) )
  189. nextLevel++;
  190. else
  191. if( checkStatement( styler, curPos, "*)" ) )
  192. nextLevel--;
  193. break;
  194. case SCE_MODULA_KEYWORD:
  195. if( checkStatement( styler, curPos, "IF" ) )
  196. nextLevel++;
  197. else
  198. if( checkStatement( styler, curPos, "BEGIN" ) )
  199. nextLevel++;
  200. else
  201. if( checkStatement( styler, curPos, "TRY" ) )
  202. nextLevel++;
  203. else
  204. if( checkStatement( styler, curPos, "LOOP" ) )
  205. nextLevel++;
  206. else
  207. if( checkStatement( styler, curPos, "FOR" ) )
  208. nextLevel++;
  209. else
  210. if( checkStatement( styler, curPos, "WHILE" ) )
  211. nextLevel++;
  212. else
  213. if( checkStatement( styler, curPos, "REPEAT" ) )
  214. nextLevel++;
  215. else
  216. if( checkStatement( styler, curPos, "UNTIL" ) )
  217. nextLevel--;
  218. else
  219. if( checkStatement( styler, curPos, "WITH" ) )
  220. nextLevel++;
  221. else
  222. if( checkStatement( styler, curPos, "CASE" ) )
  223. nextLevel++;
  224. else
  225. if( checkStatement( styler, curPos, "TYPECASE" ) )
  226. nextLevel++;
  227. else
  228. if( checkStatement( styler, curPos, "LOCK" ) )
  229. nextLevel++;
  230. else
  231. if( checkKeyIdentOper( styler, curPos, endPos, "PROCEDURE", '(' ) )
  232. nextLevel++;
  233. else
  234. if( checkKeyIdentOper( styler, curPos, endPos, "END", ';' ) ) {
  235. int cln = curLine;
  236. int clv_old = curLevel;
  237. int pos;
  238. char ch;
  239. int clv_new;
  240. while( cln > 0 ) {
  241. clv_new = styler.LevelAt( cln - 1 ) >> 16;
  242. if( clv_new < clv_old ) {
  243. nextLevel--;
  244. pos = styler.LineStart( cln );
  245. while( ( ch = styler.SafeGetCharAt( pos ) ) != '\n' ) {
  246. if( ch == 'P' ) {
  247. if( styler.StyleAt(pos) == SCE_MODULA_KEYWORD ) {
  248. if( checkKeyIdentOper( styler, pos, endPos,
  249. "PROCEDURE", '(' ) ) {
  250. break;
  251. }
  252. }
  253. }
  254. pos++;
  255. }
  256. clv_old = clv_new;
  257. }
  258. cln--;
  259. }
  260. }
  261. else
  262. if( checkKeyIdentOper( styler, curPos, endPos, "END", '.' ) )
  263. nextLevel--;
  264. else
  265. if( checkEndSemicolon( styler, curPos, endPos ) )
  266. nextLevel--;
  267. else {
  268. while( styler.StyleAt( curPos + 1 ) == SCE_MODULA_KEYWORD )
  269. curPos++;
  270. }
  271. break;
  272. default:
  273. break;
  274. }
  275. if( IsEOL( styler, curPos ) || ( curPos == endPos - 1 ) ) {
  276. int efectiveLevel = curLevel | nextLevel << 16;
  277. if( visChars == 0 )
  278. efectiveLevel |= SC_FOLDLEVELWHITEFLAG;
  279. if( curLevel < nextLevel )
  280. efectiveLevel |= SC_FOLDLEVELHEADERFLAG;
  281. if( efectiveLevel != styler.LevelAt(curLine) ) {
  282. styler.SetLevel(curLine, efectiveLevel );
  283. }
  284. curLine++;
  285. curLevel = nextLevel;
  286. if( IsEOL( styler, curPos ) && ( curPos == endPos - 1 ) ) {
  287. styler.SetLevel( curLine, ( curLevel | curLevel << 16)
  288. | SC_FOLDLEVELWHITEFLAG);
  289. }
  290. visChars = 0;
  291. }
  292. curPos++;
  293. style = styler.StyleAt( curPos );
  294. }
  295. }
  296. static inline bool skipWhiteSpaces( StyleContext & sc ) {
  297. while( isspace( sc.ch ) ) {
  298. sc.SetState( SCE_MODULA_DEFAULT );
  299. if( sc.More() )
  300. sc.Forward();
  301. else
  302. return false;
  303. }
  304. return true;
  305. }
  306. static void ColouriseModulaDoc( unsigned int startPos,
  307. int length,
  308. int initStyle,
  309. WordList *wl[],
  310. Accessor &styler ) {
  311. WordList& keyWords = *wl[0];
  312. WordList& reservedWords = *wl[1];
  313. WordList& operators = *wl[2];
  314. WordList& pragmaWords = *wl[3];
  315. WordList& escapeCodes = *wl[4];
  316. WordList& doxyKeys = *wl[5];
  317. const int BUFLEN = 128;
  318. char buf[BUFLEN];
  319. int i, kl;
  320. int charPos = 0;
  321. StyleContext sc( startPos, length, initStyle, styler );
  322. while( sc.More() ) {
  323. switch( sc.state ) {
  324. case SCE_MODULA_DEFAULT:
  325. if( ! skipWhiteSpaces( sc ) ) break;
  326. if( sc.ch == '(' && sc.chNext == '*' ) {
  327. if( sc.GetRelative(2) == '*' ) {
  328. sc.SetState( SCE_MODULA_DOXYCOMM );
  329. sc.Forward();
  330. } else {
  331. sc.SetState( SCE_MODULA_COMMENT );
  332. }
  333. sc.Forward();
  334. }
  335. else
  336. if( isalpha( sc.ch ) ) {
  337. if( isupper( sc.ch ) && isupper( sc.chNext ) ) {
  338. for( i = 0; i < BUFLEN - 1; i++ ) {
  339. buf[i] = sc.GetRelative(i);
  340. if( !isalpha( buf[i] ) && !(buf[i] == '_') )
  341. break;
  342. }
  343. kl = i;
  344. buf[kl] = 0;
  345. if( keyWords.InList( buf ) ) {
  346. sc.SetState( SCE_MODULA_KEYWORD );
  347. sc.Forward( kl );
  348. sc.SetState( SCE_MODULA_DEFAULT );
  349. continue;
  350. }
  351. else
  352. if( reservedWords.InList( buf ) ) {
  353. sc.SetState( SCE_MODULA_RESERVED );
  354. sc.Forward( kl );
  355. sc.SetState( SCE_MODULA_DEFAULT );
  356. continue;
  357. } else {
  358. /** check procedure identifier */
  359. }
  360. } else {
  361. for( i = 0; i < BUFLEN - 1; i++ ) {
  362. buf[i] = sc.GetRelative(i);
  363. if( !isalpha( buf[i] ) &&
  364. !isdigit( buf[i] ) &&
  365. !(buf[i] == '_') )
  366. break;
  367. }
  368. kl = i;
  369. buf[kl] = 0;
  370. sc.SetState( SCE_MODULA_DEFAULT );
  371. sc.Forward( kl );
  372. continue;
  373. }
  374. }
  375. else
  376. if( isdigit( sc.ch ) ) {
  377. sc.SetState( SCE_MODULA_NUMBER );
  378. continue;
  379. }
  380. else
  381. if( sc.ch == '\"' ) {
  382. sc.SetState( SCE_MODULA_STRING );
  383. }
  384. else
  385. if( sc.ch == '\'' ) {
  386. charPos = sc.currentPos;
  387. sc.SetState( SCE_MODULA_CHAR );
  388. }
  389. else
  390. if( sc.ch == '<' && sc.chNext == '*' ) {
  391. sc.SetState( SCE_MODULA_PRAGMA );
  392. sc.Forward();
  393. } else {
  394. unsigned len = IsOperator( sc, operators );
  395. if( len > 0 ) {
  396. sc.SetState( SCE_MODULA_OPERATOR );
  397. sc.Forward( len );
  398. sc.SetState( SCE_MODULA_DEFAULT );
  399. continue;
  400. } else {
  401. DEBUG_STATE( sc.currentPos, sc.ch );
  402. }
  403. }
  404. break;
  405. case SCE_MODULA_COMMENT:
  406. if( sc.ch == '*' && sc.chNext == ')' ) {
  407. sc.Forward( 2 );
  408. sc.SetState( SCE_MODULA_DEFAULT );
  409. continue;
  410. }
  411. break;
  412. case SCE_MODULA_DOXYCOMM:
  413. switch( sc.ch ) {
  414. case '*':
  415. if( sc.chNext == ')' ) {
  416. sc.Forward( 2 );
  417. sc.SetState( SCE_MODULA_DEFAULT );
  418. continue;
  419. }
  420. break;
  421. case '@':
  422. if( islower( sc.chNext ) ) {
  423. for( i = 0; i < BUFLEN - 1; i++ ) {
  424. buf[i] = sc.GetRelative(i+1);
  425. if( isspace( buf[i] ) ) break;
  426. }
  427. buf[i] = 0;
  428. kl = i;
  429. if( doxyKeys.InList( buf ) ) {
  430. sc.SetState( SCE_MODULA_DOXYKEY );
  431. sc.Forward( kl + 1 );
  432. sc.SetState( SCE_MODULA_DOXYCOMM );
  433. }
  434. }
  435. break;
  436. default:
  437. break;
  438. }
  439. break;
  440. case SCE_MODULA_NUMBER:
  441. {
  442. buf[0] = sc.ch;
  443. for( i = 1; i < BUFLEN - 1; i++ ) {
  444. buf[i] = sc.GetRelative(i);
  445. if( ! isdigit( buf[i] ) )
  446. break;
  447. }
  448. kl = i;
  449. buf[kl] = 0;
  450. switch( sc.GetRelative(kl) ) {
  451. case '_':
  452. {
  453. int base = atoi( buf );
  454. if( base < 2 || base > 16 ) {
  455. sc.SetState( SCE_MODULA_BADSTR );
  456. } else {
  457. int imax;
  458. kl++;
  459. for( i = 0; i < BUFLEN - 1; i++ ) {
  460. buf[i] = sc.GetRelative(kl+i);
  461. if( ! IsDigitOfBase( buf[i], 16 ) ) {
  462. break;
  463. }
  464. }
  465. imax = i;
  466. for( i = 0; i < imax; i++ ) {
  467. if( ! IsDigitOfBase( buf[i], base ) ) {
  468. sc.SetState( SCE_MODULA_BADSTR );
  469. break;
  470. }
  471. }
  472. kl += imax;
  473. }
  474. sc.SetState( SCE_MODULA_BASENUM );
  475. for( i = 0; i < kl; i++ ) {
  476. sc.Forward();
  477. }
  478. sc.SetState( SCE_MODULA_DEFAULT );
  479. continue;
  480. }
  481. break;
  482. case '.':
  483. if( sc.GetRelative(kl+1) == '.' ) {
  484. kl--;
  485. for( i = 0; i < kl; i++ ) {
  486. sc.Forward();
  487. }
  488. sc.Forward();
  489. sc.SetState( SCE_MODULA_DEFAULT );
  490. continue;
  491. } else {
  492. bool doNext = false;
  493. kl++;
  494. buf[0] = sc.GetRelative(kl);
  495. if( isdigit( buf[0] ) ) {
  496. for( i = 0;; i++ ) {
  497. if( !isdigit(sc.GetRelative(kl+i)) )
  498. break;
  499. }
  500. kl += i;
  501. buf[0] = sc.GetRelative(kl);
  502. switch( buf[0] )
  503. {
  504. case 'E':
  505. case 'e':
  506. case 'D':
  507. case 'd':
  508. case 'X':
  509. case 'x':
  510. kl++;
  511. buf[0] = sc.GetRelative(kl);
  512. if( buf[0] == '-' || buf[0] == '+' ) {
  513. kl++;
  514. }
  515. buf[0] = sc.GetRelative(kl);
  516. if( isdigit( buf[0] ) ) {
  517. for( i = 0;; i++ ) {
  518. if( !isdigit(sc.GetRelative(kl+i)) ) {
  519. buf[0] = sc.GetRelative(kl+i);
  520. break;
  521. }
  522. }
  523. kl += i;
  524. doNext = true;
  525. } else {
  526. sc.SetState( SCE_MODULA_BADSTR );
  527. }
  528. break;
  529. default:
  530. doNext = true;
  531. break;
  532. }
  533. } else {
  534. sc.SetState( SCE_MODULA_BADSTR );
  535. }
  536. if( doNext ) {
  537. if( ! isspace( buf[0] ) &&
  538. buf[0] != ')' &&
  539. buf[0] != '>' &&
  540. buf[0] != '<' &&
  541. buf[0] != '=' &&
  542. buf[0] != '#' &&
  543. buf[0] != '+' &&
  544. buf[0] != '-' &&
  545. buf[0] != '*' &&
  546. buf[0] != '/' &&
  547. buf[0] != ',' &&
  548. buf[0] != ';'
  549. ) {
  550. sc.SetState( SCE_MODULA_BADSTR );
  551. } else {
  552. kl--;
  553. }
  554. }
  555. }
  556. sc.SetState( SCE_MODULA_FLOAT );
  557. for( i = 0; i < kl; i++ ) {
  558. sc.Forward();
  559. }
  560. sc.SetState( SCE_MODULA_DEFAULT );
  561. continue;
  562. break;
  563. default:
  564. for( i = 0; i < kl; i++ ) {
  565. sc.Forward();
  566. }
  567. break;
  568. }
  569. sc.SetState( SCE_MODULA_DEFAULT );
  570. continue;
  571. }
  572. break;
  573. case SCE_MODULA_STRING:
  574. if( sc.ch == '\"' ) {
  575. sc.Forward();
  576. sc.SetState( SCE_MODULA_DEFAULT );
  577. continue;
  578. } else {
  579. if( sc.ch == '\\' ) {
  580. i = 1;
  581. if( IsDigitOfBase( sc.chNext, 8 ) ) {
  582. for( i = 1; i < BUFLEN - 1; i++ ) {
  583. if( ! IsDigitOfBase(sc.GetRelative(i+1), 8 ) )
  584. break;
  585. }
  586. if( i == 3 ) {
  587. sc.SetState( SCE_MODULA_STRSPEC );
  588. } else {
  589. sc.SetState( SCE_MODULA_BADSTR );
  590. }
  591. } else {
  592. buf[0] = sc.chNext;
  593. buf[1] = 0;
  594. if( escapeCodes.InList( buf ) ) {
  595. sc.SetState( SCE_MODULA_STRSPEC );
  596. } else {
  597. sc.SetState( SCE_MODULA_BADSTR );
  598. }
  599. }
  600. sc.Forward(i+1);
  601. sc.SetState( SCE_MODULA_STRING );
  602. continue;
  603. }
  604. }
  605. break;
  606. case SCE_MODULA_CHAR:
  607. if( sc.ch == '\'' ) {
  608. sc.Forward();
  609. sc.SetState( SCE_MODULA_DEFAULT );
  610. continue;
  611. }
  612. else
  613. if( ( sc.currentPos - charPos ) == 1 ) {
  614. if( sc.ch == '\\' ) {
  615. i = 1;
  616. if( IsDigitOfBase( sc.chNext, 8 ) ) {
  617. for( i = 1; i < BUFLEN - 1; i++ ) {
  618. if( ! IsDigitOfBase(sc.GetRelative(i+1), 8 ) )
  619. break;
  620. }
  621. if( i == 3 ) {
  622. sc.SetState( SCE_MODULA_CHARSPEC );
  623. } else {
  624. sc.SetState( SCE_MODULA_BADSTR );
  625. }
  626. } else {
  627. buf[0] = sc.chNext;
  628. buf[1] = 0;
  629. if( escapeCodes.InList( buf ) ) {
  630. sc.SetState( SCE_MODULA_CHARSPEC );
  631. } else {
  632. sc.SetState( SCE_MODULA_BADSTR );
  633. }
  634. }
  635. sc.Forward(i+1);
  636. sc.SetState( SCE_MODULA_CHAR );
  637. continue;
  638. }
  639. } else {
  640. sc.SetState( SCE_MODULA_BADSTR );
  641. sc.Forward();
  642. sc.SetState( SCE_MODULA_CHAR );
  643. continue;
  644. }
  645. break;
  646. case SCE_MODULA_PRAGMA:
  647. if( sc.ch == '*' && sc.chNext == '>' ) {
  648. sc.Forward();
  649. sc.Forward();
  650. sc.SetState( SCE_MODULA_DEFAULT );
  651. continue;
  652. }
  653. else
  654. if( isupper( sc.ch ) && isupper( sc.chNext ) ) {
  655. buf[0] = sc.ch;
  656. buf[1] = sc.chNext;
  657. for( i = 2; i < BUFLEN - 1; i++ ) {
  658. buf[i] = sc.GetRelative(i);
  659. if( !isupper( buf[i] ) )
  660. break;
  661. }
  662. kl = i;
  663. buf[kl] = 0;
  664. if( pragmaWords.InList( buf ) ) {
  665. sc.SetState( SCE_MODULA_PRGKEY );
  666. sc.Forward( kl );
  667. sc.SetState( SCE_MODULA_PRAGMA );
  668. continue;
  669. }
  670. }
  671. break;
  672. default:
  673. break;
  674. }
  675. sc.Forward();
  676. }
  677. sc.Complete();
  678. }
  679. static const char *const modulaWordListDesc[] =
  680. {
  681. "Keywords",
  682. "ReservedKeywords",
  683. "Operators",
  684. "PragmaKeyswords",
  685. "EscapeCodes",
  686. "DoxygeneKeywords",
  687. 0
  688. };
  689. LexerModule lmModula( SCLEX_MODULA, ColouriseModulaDoc, "modula", FoldModulaDoc,
  690. modulaWordListDesc);