LexForth.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  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 IsAWordStart(int ch) {
  26. return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.');
  27. }
  28. static inline bool IsANumChar(int ch) {
  29. return (ch < 0x80) && (isxdigit(ch) || ch == '.' || ch == 'e' || ch == 'E' );
  30. }
  31. static inline bool IsASpaceChar(int ch) {
  32. return (ch < 0x80) && isspace(ch);
  33. }
  34. static void ColouriseForthDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordLists[],
  35. Accessor &styler) {
  36. WordList &control = *keywordLists[0];
  37. WordList &keyword = *keywordLists[1];
  38. WordList &defword = *keywordLists[2];
  39. WordList &preword1 = *keywordLists[3];
  40. WordList &preword2 = *keywordLists[4];
  41. WordList &strings = *keywordLists[5];
  42. StyleContext sc(startPos, length, initStyle, styler);
  43. for (; sc.More(); sc.Forward())
  44. {
  45. // Determine if the current state should terminate.
  46. if (sc.state == SCE_FORTH_COMMENT) {
  47. if (sc.atLineEnd) {
  48. sc.SetState(SCE_FORTH_DEFAULT);
  49. }
  50. }else if (sc.state == SCE_FORTH_COMMENT_ML) {
  51. if (sc.ch == ')') {
  52. sc.ForwardSetState(SCE_FORTH_DEFAULT);
  53. }
  54. }else if (sc.state == SCE_FORTH_IDENTIFIER || sc.state == SCE_FORTH_NUMBER) {
  55. // handle numbers here too, because what we thought was a number might
  56. // turn out to be a keyword e.g. 2DUP
  57. if (IsASpaceChar(sc.ch) ) {
  58. char s[100];
  59. sc.GetCurrentLowered(s, sizeof(s));
  60. int newState = sc.state == SCE_FORTH_NUMBER ? SCE_FORTH_NUMBER : SCE_FORTH_DEFAULT;
  61. if (control.InList(s)) {
  62. sc.ChangeState(SCE_FORTH_CONTROL);
  63. } else if (keyword.InList(s)) {
  64. sc.ChangeState(SCE_FORTH_KEYWORD);
  65. } else if (defword.InList(s)) {
  66. sc.ChangeState(SCE_FORTH_DEFWORD);
  67. } else if (preword1.InList(s)) {
  68. sc.ChangeState(SCE_FORTH_PREWORD1);
  69. } else if (preword2.InList(s)) {
  70. sc.ChangeState(SCE_FORTH_PREWORD2);
  71. } else if (strings.InList(s)) {
  72. sc.ChangeState(SCE_FORTH_STRING);
  73. newState = SCE_FORTH_STRING;
  74. }
  75. sc.SetState(newState);
  76. }
  77. if (sc.state == SCE_FORTH_NUMBER) {
  78. if (IsASpaceChar(sc.ch)) {
  79. sc.SetState(SCE_FORTH_DEFAULT);
  80. } else if (!IsANumChar(sc.ch)) {
  81. sc.ChangeState(SCE_FORTH_IDENTIFIER);
  82. }
  83. }
  84. }else if (sc.state == SCE_FORTH_STRING) {
  85. if (sc.ch == '\"') {
  86. sc.ForwardSetState(SCE_FORTH_DEFAULT);
  87. }
  88. }else if (sc.state == SCE_FORTH_LOCALE) {
  89. if (sc.ch == '}') {
  90. sc.ForwardSetState(SCE_FORTH_DEFAULT);
  91. }
  92. }else if (sc.state == SCE_FORTH_DEFWORD) {
  93. if (IsASpaceChar(sc.ch)) {
  94. sc.SetState(SCE_FORTH_DEFAULT);
  95. }
  96. }
  97. // Determine if a new state should be entered.
  98. if (sc.state == SCE_FORTH_DEFAULT) {
  99. if (sc.ch == '\\'){
  100. sc.SetState(SCE_FORTH_COMMENT);
  101. } else if (sc.ch == '(' &&
  102. (sc.atLineStart || IsASpaceChar(sc.chPrev)) &&
  103. (sc.atLineEnd || IsASpaceChar(sc.chNext))) {
  104. sc.SetState(SCE_FORTH_COMMENT_ML);
  105. } else if ( (sc.ch == '$' && (IsASCII(sc.chNext) && isxdigit(sc.chNext))) ) {
  106. // number starting with $ is a hex number
  107. sc.SetState(SCE_FORTH_NUMBER);
  108. while(sc.More() && IsASCII(sc.chNext) && isxdigit(sc.chNext))
  109. sc.Forward();
  110. } else if ( (sc.ch == '%' && (IsASCII(sc.chNext) && (sc.chNext == '0' || sc.chNext == '1'))) ) {
  111. // number starting with % is binary
  112. sc.SetState(SCE_FORTH_NUMBER);
  113. while(sc.More() && IsASCII(sc.chNext) && (sc.chNext == '0' || sc.chNext == '1'))
  114. sc.Forward();
  115. } else if ( IsASCII(sc.ch) &&
  116. (isxdigit(sc.ch) || ((sc.ch == '.' || sc.ch == '-') && IsASCII(sc.chNext) && isxdigit(sc.chNext)) )
  117. ){
  118. sc.SetState(SCE_FORTH_NUMBER);
  119. } else if (IsAWordStart(sc.ch)) {
  120. sc.SetState(SCE_FORTH_IDENTIFIER);
  121. } else if (sc.ch == '{') {
  122. sc.SetState(SCE_FORTH_LOCALE);
  123. } else if (sc.ch == ':' && IsASCII(sc.chNext) && isspace(sc.chNext)) {
  124. // highlight word definitions e.g. : GCD ( n n -- n ) ..... ;
  125. // ^ ^^^
  126. sc.SetState(SCE_FORTH_DEFWORD);
  127. while(sc.More() && IsASCII(sc.chNext) && isspace(sc.chNext))
  128. sc.Forward();
  129. } else if (sc.ch == ';' &&
  130. (sc.atLineStart || IsASpaceChar(sc.chPrev)) &&
  131. (sc.atLineEnd || IsASpaceChar(sc.chNext)) ) {
  132. // mark the ';' that ends a word
  133. sc.SetState(SCE_FORTH_DEFWORD);
  134. sc.ForwardSetState(SCE_FORTH_DEFAULT);
  135. }
  136. }
  137. }
  138. sc.Complete();
  139. }
  140. static void FoldForthDoc(Sci_PositionU, Sci_Position, int, WordList *[],
  141. Accessor &) {
  142. }
  143. static const char * const forthWordLists[] = {
  144. "control keywords",
  145. "keywords",
  146. "definition words",
  147. "prewords with one argument",
  148. "prewords with two arguments",
  149. "string definition keywords",
  150. 0,
  151. };
  152. LexerModule lmForth(SCLEX_FORTH, ColouriseForthDoc, "forth", FoldForthDoc, forthWordLists);