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

# · C++ · 179 lines · 168 code · 5 blank · 6 comment · 8 complexity · 134680251cb6bfe8f56ddcd477fd4ab6 MD5 · raw file

  1. // Scintilla source code edit control
  2. /** @file LexForth.cxx
  3. ** Lexer for FORTH
  4. **/
  5. // Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
  6. // The License.txt file describes the conditions under which this software may be distributed.
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <stdio.h>
  10. #include <stdarg.h>
  11. #include <assert.h>
  12. #include <ctype.h>
  13. #include "ILexer.h"
  14. #include "Scintilla.h"
  15. #include "SciLexer.h"
  16. #include "WordList.h"
  17. #include "LexAccessor.h"
  18. #include "Accessor.h"
  19. #include "StyleContext.h"
  20. #include "CharacterSet.h"
  21. #include "LexerModule.h"
  22. #ifdef SCI_NAMESPACE
  23. using namespace Scintilla;
  24. #endif
  25. static inline bool IsAWordChar(int ch) {
  26. return (ch < 0x80) && (isalnum(ch) || ch == '.' ||
  27. ch == '_' || ch == '?' || ch == '"' || ch == '@' ||
  28. ch == '!' || ch == '[' || ch == ']' || ch == '/' ||
  29. ch == '+' || ch == '-' || ch == '*' || ch == '<' ||
  30. ch == '>' || ch == '=' || ch == ';' || ch == '(' ||
  31. ch == ')' );
  32. }
  33. static inline bool IsAWordStart(int ch) {
  34. return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.');
  35. }
  36. static inline bool IsANumChar(int ch) {
  37. return (ch < 0x80) && (isxdigit(ch) || ch == '.' || ch == 'e' || ch == 'E' );
  38. }
  39. static inline bool IsASpaceChar(int ch) {
  40. return (ch < 0x80) && isspace(ch);
  41. }
  42. static void ColouriseForthDoc(unsigned int startPos, int length, int initStyle, WordList *keywordLists[],
  43. Accessor &styler) {
  44. WordList &control = *keywordLists[0];
  45. WordList &keyword = *keywordLists[1];
  46. WordList &defword = *keywordLists[2];
  47. WordList &preword1 = *keywordLists[3];
  48. WordList &preword2 = *keywordLists[4];
  49. WordList &strings = *keywordLists[5];
  50. StyleContext sc(startPos, length, initStyle, styler);
  51. for (; sc.More(); sc.Forward())
  52. {
  53. // Determine if the current state should terminate.
  54. if (sc.state == SCE_FORTH_COMMENT) {
  55. if (sc.atLineEnd) {
  56. sc.SetState(SCE_FORTH_DEFAULT);
  57. }
  58. }else if (sc.state == SCE_FORTH_COMMENT_ML) {
  59. if (sc.ch == ')') {
  60. sc.ForwardSetState(SCE_FORTH_DEFAULT);
  61. }
  62. }else if (sc.state == SCE_FORTH_IDENTIFIER || sc.state == SCE_FORTH_NUMBER) {
  63. // handle numbers here too, because what we thought was a number might
  64. // turn out to be a keyword e.g. 2DUP
  65. if (IsASpaceChar(sc.ch) ) {
  66. char s[100];
  67. sc.GetCurrentLowered(s, sizeof(s));
  68. int newState = sc.state == SCE_FORTH_NUMBER ? SCE_FORTH_NUMBER : SCE_FORTH_DEFAULT;
  69. if (control.InList(s)) {
  70. sc.ChangeState(SCE_FORTH_CONTROL);
  71. } else if (keyword.InList(s)) {
  72. sc.ChangeState(SCE_FORTH_KEYWORD);
  73. } else if (defword.InList(s)) {
  74. sc.ChangeState(SCE_FORTH_DEFWORD);
  75. } else if (preword1.InList(s)) {
  76. sc.ChangeState(SCE_FORTH_PREWORD1);
  77. } else if (preword2.InList(s)) {
  78. sc.ChangeState(SCE_FORTH_PREWORD2);
  79. } else if (strings.InList(s)) {
  80. sc.ChangeState(SCE_FORTH_STRING);
  81. newState = SCE_FORTH_STRING;
  82. }
  83. sc.SetState(newState);
  84. }
  85. if (sc.state == SCE_FORTH_NUMBER) {
  86. if (IsASpaceChar(sc.ch)) {
  87. sc.SetState(SCE_FORTH_DEFAULT);
  88. } else if (!IsANumChar(sc.ch)) {
  89. sc.ChangeState(SCE_FORTH_IDENTIFIER);
  90. }
  91. }
  92. }else if (sc.state == SCE_FORTH_STRING) {
  93. if (sc.ch == '\"') {
  94. sc.ForwardSetState(SCE_FORTH_DEFAULT);
  95. }
  96. }else if (sc.state == SCE_FORTH_LOCALE) {
  97. if (sc.ch == '}') {
  98. sc.ForwardSetState(SCE_FORTH_DEFAULT);
  99. }
  100. }else if (sc.state == SCE_FORTH_DEFWORD) {
  101. if (IsASpaceChar(sc.ch)) {
  102. sc.SetState(SCE_FORTH_DEFAULT);
  103. }
  104. }
  105. // Determine if a new state should be entered.
  106. if (sc.state == SCE_FORTH_DEFAULT) {
  107. if (sc.ch == '\\'){
  108. sc.SetState(SCE_FORTH_COMMENT);
  109. } else if (sc.ch == '(' &&
  110. (sc.atLineStart || IsASpaceChar(sc.chPrev)) &&
  111. (sc.atLineEnd || IsASpaceChar(sc.chNext))) {
  112. sc.SetState(SCE_FORTH_COMMENT_ML);
  113. } else if ( (sc.ch == '$' && (isascii(sc.chNext) && isxdigit(sc.chNext))) ) {
  114. // number starting with $ is a hex number
  115. sc.SetState(SCE_FORTH_NUMBER);
  116. while(sc.More() && isascii(sc.chNext) && isxdigit(sc.chNext))
  117. sc.Forward();
  118. } else if ( (sc.ch == '%' && (isascii(sc.chNext) && (sc.chNext == '0' || sc.chNext == '1'))) ) {
  119. // number starting with % is binary
  120. sc.SetState(SCE_FORTH_NUMBER);
  121. while(sc.More() && isascii(sc.chNext) && (sc.chNext == '0' || sc.chNext == '1'))
  122. sc.Forward();
  123. } else if ( isascii(sc.ch) &&
  124. (isxdigit(sc.ch) || ((sc.ch == '.' || sc.ch == '-') && isascii(sc.chNext) && isxdigit(sc.chNext)) )
  125. ){
  126. sc.SetState(SCE_FORTH_NUMBER);
  127. } else if (IsAWordStart(sc.ch)) {
  128. sc.SetState(SCE_FORTH_IDENTIFIER);
  129. } else if (sc.ch == '{') {
  130. sc.SetState(SCE_FORTH_LOCALE);
  131. } else if (sc.ch == ':' && isascii(sc.chNext) && isspace(sc.chNext)) {
  132. // highlight word definitions e.g. : GCD ( n n -- n ) ..... ;
  133. // ^ ^^^
  134. sc.SetState(SCE_FORTH_DEFWORD);
  135. while(sc.More() && isascii(sc.chNext) && isspace(sc.chNext))
  136. sc.Forward();
  137. } else if (sc.ch == ';' &&
  138. (sc.atLineStart || IsASpaceChar(sc.chPrev)) &&
  139. (sc.atLineEnd || IsASpaceChar(sc.chNext)) ) {
  140. // mark the ';' that ends a word
  141. sc.SetState(SCE_FORTH_DEFWORD);
  142. sc.ForwardSetState(SCE_FORTH_DEFAULT);
  143. }
  144. }
  145. }
  146. sc.Complete();
  147. }
  148. static void FoldForthDoc(unsigned int, int, int, WordList *[],
  149. Accessor &) {
  150. }
  151. static const char * const forthWordLists[] = {
  152. "control keywords",
  153. "keywords",
  154. "definition words",
  155. "prewords with one argument",
  156. "prewords with two arguments",
  157. "string definition keywords",
  158. 0,
  159. };
  160. LexerModule lmForth(SCLEX_FORTH, ColouriseForthDoc, "forth", FoldForthDoc, forthWordLists);