LexMMIXAL.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. // Scintilla source code edit control
  2. /** @file LexMMIXAL.cxx
  3. ** Lexer for MMIX Assembler Language.
  4. ** Written by Christoph Hösler <christoph.hoesler@student.uni-tuebingen.de>
  5. ** For information about MMIX visit http://www-cs-faculty.stanford.edu/~knuth/mmix.html
  6. **/
  7. // Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
  8. // The License.txt file describes the conditions under which this software may be distributed.
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <stdio.h>
  12. #include <stdarg.h>
  13. #include <assert.h>
  14. #include <ctype.h>
  15. #include "ILexer.h"
  16. #include "Scintilla.h"
  17. #include "SciLexer.h"
  18. #include "WordList.h"
  19. #include "LexAccessor.h"
  20. #include "Accessor.h"
  21. #include "StyleContext.h"
  22. #include "CharacterSet.h"
  23. #include "LexerModule.h"
  24. #ifdef SCI_NAMESPACE
  25. using namespace Scintilla;
  26. #endif
  27. static inline bool IsAWordChar(const int ch) {
  28. return (ch < 0x80) && (isalnum(ch) || ch == ':' || ch == '_');
  29. }
  30. inline bool isMMIXALOperator(char ch) {
  31. if (IsASCII(ch) && isalnum(ch))
  32. return false;
  33. if (ch == '+' || ch == '-' || ch == '|' || ch == '^' ||
  34. ch == '*' || ch == '/' ||
  35. ch == '%' || ch == '<' || ch == '>' || ch == '&' ||
  36. ch == '~' || ch == '$' ||
  37. ch == ',' || ch == '(' || ch == ')' ||
  38. ch == '[' || ch == ']')
  39. return true;
  40. return false;
  41. }
  42. static void ColouriseMMIXALDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordlists[],
  43. Accessor &styler) {
  44. WordList &opcodes = *keywordlists[0];
  45. WordList &special_register = *keywordlists[1];
  46. WordList &predef_symbols = *keywordlists[2];
  47. StyleContext sc(startPos, length, initStyle, styler);
  48. for (; sc.More(); sc.Forward())
  49. {
  50. // No EOL continuation
  51. if (sc.atLineStart) {
  52. if (sc.ch == '@' && sc.chNext == 'i') {
  53. sc.SetState(SCE_MMIXAL_INCLUDE);
  54. } else {
  55. sc.SetState(SCE_MMIXAL_LEADWS);
  56. }
  57. }
  58. // Check if first non whitespace character in line is alphanumeric
  59. if (sc.state == SCE_MMIXAL_LEADWS && !isspace(sc.ch)) { // LEADWS
  60. if(!IsAWordChar(sc.ch)) {
  61. sc.SetState(SCE_MMIXAL_COMMENT);
  62. } else {
  63. if(sc.atLineStart) {
  64. sc.SetState(SCE_MMIXAL_LABEL);
  65. } else {
  66. sc.SetState(SCE_MMIXAL_OPCODE_PRE);
  67. }
  68. }
  69. }
  70. // Determine if the current state should terminate.
  71. if (sc.state == SCE_MMIXAL_OPERATOR) { // OPERATOR
  72. sc.SetState(SCE_MMIXAL_OPERANDS);
  73. } else if (sc.state == SCE_MMIXAL_NUMBER) { // NUMBER
  74. if (!isdigit(sc.ch)) {
  75. if (IsAWordChar(sc.ch)) {
  76. char s[100];
  77. sc.GetCurrent(s, sizeof(s));
  78. sc.ChangeState(SCE_MMIXAL_REF);
  79. sc.SetState(SCE_MMIXAL_REF);
  80. } else {
  81. sc.SetState(SCE_MMIXAL_OPERANDS);
  82. }
  83. }
  84. } else if (sc.state == SCE_MMIXAL_LABEL) { // LABEL
  85. if (!IsAWordChar(sc.ch) ) {
  86. sc.SetState(SCE_MMIXAL_OPCODE_PRE);
  87. }
  88. } else if (sc.state == SCE_MMIXAL_REF) { // REF
  89. if (!IsAWordChar(sc.ch) ) {
  90. char s[100];
  91. sc.GetCurrent(s, sizeof(s));
  92. if (*s == ':') { // ignore base prefix for match
  93. for (size_t i = 0; i != sizeof(s); ++i) {
  94. *(s+i) = *(s+i+1);
  95. }
  96. }
  97. if (special_register.InList(s)) {
  98. sc.ChangeState(SCE_MMIXAL_REGISTER);
  99. } else if (predef_symbols.InList(s)) {
  100. sc.ChangeState(SCE_MMIXAL_SYMBOL);
  101. }
  102. sc.SetState(SCE_MMIXAL_OPERANDS);
  103. }
  104. } else if (sc.state == SCE_MMIXAL_OPCODE_PRE) { // OPCODE_PRE
  105. if (!isspace(sc.ch)) {
  106. sc.SetState(SCE_MMIXAL_OPCODE);
  107. }
  108. } else if (sc.state == SCE_MMIXAL_OPCODE) { // OPCODE
  109. if (!IsAWordChar(sc.ch) ) {
  110. char s[100];
  111. sc.GetCurrent(s, sizeof(s));
  112. if (opcodes.InList(s)) {
  113. sc.ChangeState(SCE_MMIXAL_OPCODE_VALID);
  114. } else {
  115. sc.ChangeState(SCE_MMIXAL_OPCODE_UNKNOWN);
  116. }
  117. sc.SetState(SCE_MMIXAL_OPCODE_POST);
  118. }
  119. } else if (sc.state == SCE_MMIXAL_STRING) { // STRING
  120. if (sc.ch == '\"') {
  121. sc.ForwardSetState(SCE_MMIXAL_OPERANDS);
  122. } else if (sc.atLineEnd) {
  123. sc.ForwardSetState(SCE_MMIXAL_OPERANDS);
  124. }
  125. } else if (sc.state == SCE_MMIXAL_CHAR) { // CHAR
  126. if (sc.ch == '\'') {
  127. sc.ForwardSetState(SCE_MMIXAL_OPERANDS);
  128. } else if (sc.atLineEnd) {
  129. sc.ForwardSetState(SCE_MMIXAL_OPERANDS);
  130. }
  131. } else if (sc.state == SCE_MMIXAL_REGISTER) { // REGISTER
  132. if (!isdigit(sc.ch)) {
  133. sc.SetState(SCE_MMIXAL_OPERANDS);
  134. }
  135. } else if (sc.state == SCE_MMIXAL_HEX) { // HEX
  136. if (!isxdigit(sc.ch)) {
  137. sc.SetState(SCE_MMIXAL_OPERANDS);
  138. }
  139. }
  140. // Determine if a new state should be entered.
  141. if (sc.state == SCE_MMIXAL_OPCODE_POST || // OPCODE_POST
  142. sc.state == SCE_MMIXAL_OPERANDS) { // OPERANDS
  143. if (sc.state == SCE_MMIXAL_OPERANDS && isspace(sc.ch)) {
  144. if (!sc.atLineEnd) {
  145. sc.SetState(SCE_MMIXAL_COMMENT);
  146. }
  147. } else if (isdigit(sc.ch)) {
  148. sc.SetState(SCE_MMIXAL_NUMBER);
  149. } else if (IsAWordChar(sc.ch) || sc.Match('@')) {
  150. sc.SetState(SCE_MMIXAL_REF);
  151. } else if (sc.Match('\"')) {
  152. sc.SetState(SCE_MMIXAL_STRING);
  153. } else if (sc.Match('\'')) {
  154. sc.SetState(SCE_MMIXAL_CHAR);
  155. } else if (sc.Match('$')) {
  156. sc.SetState(SCE_MMIXAL_REGISTER);
  157. } else if (sc.Match('#')) {
  158. sc.SetState(SCE_MMIXAL_HEX);
  159. } else if (isMMIXALOperator(static_cast<char>(sc.ch))) {
  160. sc.SetState(SCE_MMIXAL_OPERATOR);
  161. }
  162. }
  163. }
  164. sc.Complete();
  165. }
  166. static const char * const MMIXALWordListDesc[] = {
  167. "Operation Codes",
  168. "Special Register",
  169. "Predefined Symbols",
  170. 0
  171. };
  172. LexerModule lmMMIXAL(SCLEX_MMIXAL, ColouriseMMIXALDoc, "mmixal", 0, MMIXALWordListDesc);