mirror of
				https://github.com/notepad-plus-plus/notepad-plus-plus.git
				synced 2025-11-03 21:14:08 +01:00 
			
		
		
		
	Update with https://www.scintilla.org/scintilla521.zip https://www.scintilla.org/lexilla515.zip - fix setting to bring Scintilla::PositionCR from ScintillaStructures.h inline with Sci_Position.h Sci_PositionCR - add workaround to enable lexer for searchResult commented out SCI_SETILEXER call on searchResult to get one result which is correctly handled by the lexer, added comment about the current problem with property @MarkingsStruct which seems to disappear after call to SCI_SETILEXER or CreateLexer - corrected usage of ObjC lexer - removed unnecessary filter stuff - use own sections for scintilla and lexilla build targets and allow parallel builds - as libscilex is no longer existing, changed to libscintilla - adapt makefiles and cmake - use VS2019 - started simple changes for createlexer adaptations, nullpointercheck missing on return of lexer name from deprecated LexerNameFromID -> undefined behaviour - movement from id -> lexer name, mostly done via LexerNameFromID + switching off corresponding compiler warning - changed to SCI_SETILEXER from SCI_SETLEXER, SCI_SETLEXERLANGUAGE needs to be corrected, see Scintilla5Migration.html - just commented out: SCI_LOADLEXERLIBRARY Fix #10504, close #11419
		
			
				
	
	
		
			435 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			435 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
// Scintilla source code edit control
 | 
						|
// Nimrod lexer
 | 
						|
// (c) 2009 Andreas Rumpf
 | 
						|
/** @file LexNimrod.cxx
 | 
						|
 ** Lexer for Nimrod.
 | 
						|
 **/
 | 
						|
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
 | 
						|
// The License.txt file describes the conditions under which this software may be distributed.
 | 
						|
 | 
						|
#include <stdlib.h>
 | 
						|
#include <string.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdarg.h>
 | 
						|
#include <assert.h>
 | 
						|
#include <ctype.h>
 | 
						|
 | 
						|
#include <string>
 | 
						|
#include <string_view>
 | 
						|
 | 
						|
#include "ILexer.h"
 | 
						|
#include "Scintilla.h"
 | 
						|
#include "SciLexer.h"
 | 
						|
 | 
						|
#include "WordList.h"
 | 
						|
#include "LexAccessor.h"
 | 
						|
#include "Accessor.h"
 | 
						|
#include "StyleContext.h"
 | 
						|
#include "CharacterSet.h"
 | 
						|
#include "LexerModule.h"
 | 
						|
 | 
						|
using namespace Lexilla;
 | 
						|
 | 
						|
static inline bool IsAWordChar(int ch) {
 | 
						|
	return (ch >= 0x80) || isalnum(ch) || ch == '_';
 | 
						|
}
 | 
						|
 | 
						|
static Sci_Position tillEndOfTripleQuote(Accessor &styler, Sci_Position pos, Sci_Position max) {
 | 
						|
  /* search for """ */
 | 
						|
  for (;;) {
 | 
						|
    if (styler.SafeGetCharAt(pos, '\0') == '\0') return pos;
 | 
						|
    if (pos >= max) return pos;
 | 
						|
    if (styler.Match(pos, "\"\"\"")) {
 | 
						|
      return pos + 2;
 | 
						|
    }
 | 
						|
    pos++;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
#define CR 13 /* use both because Scite allows changing the line ending */
 | 
						|
#define LF 10
 | 
						|
 | 
						|
static bool inline isNewLine(int ch) {
 | 
						|
  return ch == CR || ch == LF;
 | 
						|
}
 | 
						|
 | 
						|
static Sci_Position scanString(Accessor &styler, Sci_Position pos, Sci_Position max, bool rawMode) {
 | 
						|
  for (;;) {
 | 
						|
    if (pos >= max) return pos;
 | 
						|
    char ch = styler.SafeGetCharAt(pos, '\0');
 | 
						|
    if (ch == CR || ch == LF || ch == '\0') return pos;
 | 
						|
    if (ch == '"') return pos;
 | 
						|
    if (ch == '\\' && !rawMode) {
 | 
						|
      pos += 2;
 | 
						|
    } else {
 | 
						|
      pos++;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
static Sci_Position scanChar(Accessor &styler, Sci_Position pos, Sci_Position max) {
 | 
						|
  for (;;) {
 | 
						|
    if (pos >= max) return pos;
 | 
						|
    char ch = styler.SafeGetCharAt(pos, '\0');
 | 
						|
    if (ch == CR || ch == LF || ch == '\0') return pos;
 | 
						|
    if (ch == '\'' && !isalnum(styler.SafeGetCharAt(pos+1, '\0')) )
 | 
						|
      return pos;
 | 
						|
    if (ch == '\\') {
 | 
						|
      pos += 2;
 | 
						|
    } else {
 | 
						|
      pos++;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
static Sci_Position scanIdent(Accessor &styler, Sci_Position pos, WordList &keywords) {
 | 
						|
  char buf[100]; /* copy to lowercase and ignore underscores */
 | 
						|
  Sci_Position i = 0;
 | 
						|
 | 
						|
  for (;;) {
 | 
						|
    char ch = styler.SafeGetCharAt(pos, '\0');
 | 
						|
    if (!IsAWordChar(ch)) break;
 | 
						|
    if (ch != '_' && i < ((int)sizeof(buf))-1) {
 | 
						|
      buf[i] = static_cast<char>(tolower(ch));
 | 
						|
      i++;
 | 
						|
    }
 | 
						|
    pos++;
 | 
						|
  }
 | 
						|
  buf[i] = '\0';
 | 
						|
  /* look for keyword */
 | 
						|
  if (keywords.InList(buf)) {
 | 
						|
    styler.ColourTo(pos-1, SCE_P_WORD);
 | 
						|
  } else {
 | 
						|
    styler.ColourTo(pos-1, SCE_P_IDENTIFIER);
 | 
						|
  }
 | 
						|
  return pos;
 | 
						|
}
 | 
						|
 | 
						|
static Sci_Position scanNumber(Accessor &styler, Sci_Position pos) {
 | 
						|
  char ch, ch2;
 | 
						|
  ch = styler.SafeGetCharAt(pos, '\0');
 | 
						|
  ch2 = styler.SafeGetCharAt(pos+1, '\0');
 | 
						|
  if (ch == '0' && (ch2 == 'b' || ch2 == 'B')) {
 | 
						|
    /* binary number: */
 | 
						|
    pos += 2;
 | 
						|
    for (;;) {
 | 
						|
      ch = styler.SafeGetCharAt(pos, '\0');
 | 
						|
      if (ch == '_' || (ch >= '0' && ch <= '1')) ++pos;
 | 
						|
      else break;
 | 
						|
    }
 | 
						|
  } else if (ch == '0' &&
 | 
						|
            (ch2 == 'o' || ch2 == 'O' || ch2 == 'c' || ch2 == 'C')) {
 | 
						|
    /* octal number: */
 | 
						|
    pos += 2;
 | 
						|
    for (;;) {
 | 
						|
      ch = styler.SafeGetCharAt(pos, '\0');
 | 
						|
      if (ch == '_' || (ch >= '0' && ch <= '7')) ++pos;
 | 
						|
      else break;
 | 
						|
    }
 | 
						|
  } else if (ch == '0' && (ch2 == 'x' || ch2 == 'X')) {
 | 
						|
    /* hexadecimal number: */
 | 
						|
    pos += 2;
 | 
						|
    for (;;) {
 | 
						|
      ch = styler.SafeGetCharAt(pos, '\0');
 | 
						|
      if (ch == '_' || (ch >= '0' && ch <= '9')
 | 
						|
          || (ch >= 'a' && ch <= 'f')
 | 
						|
          || (ch >= 'A' && ch <= 'F')) ++pos;
 | 
						|
      else break;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    // skip decimal part:
 | 
						|
    for (;;) {
 | 
						|
      ch = styler.SafeGetCharAt(pos, '\0');
 | 
						|
      if (ch == '_' || (ch >= '0' && ch <= '9')) ++pos;
 | 
						|
      else break;
 | 
						|
    }
 | 
						|
    ch2 = styler.SafeGetCharAt(pos+1, '\0');
 | 
						|
    if (ch == '.' && ch2 >= '0' && ch2 <= '9') {
 | 
						|
      ++pos; // skip '.'
 | 
						|
      for (;;) {
 | 
						|
        ch = styler.SafeGetCharAt(pos, '\0');
 | 
						|
        if (ch == '_' || (ch >= '0' && ch <= '9')) ++pos;
 | 
						|
        else break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    if (ch == 'e' || ch == 'E') {
 | 
						|
      ++pos;
 | 
						|
      ch = styler.SafeGetCharAt(pos, '\0');
 | 
						|
      if (ch == '-' || ch == '+') ++pos;
 | 
						|
      for (;;) {
 | 
						|
        ch = styler.SafeGetCharAt(pos, '\0');
 | 
						|
        if (ch == '_' || (ch >= '0' && ch <= '9')) ++pos;
 | 
						|
        else break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (ch == '\'') {
 | 
						|
    /* a type suffix: */
 | 
						|
    pos++;
 | 
						|
    for (;;) {
 | 
						|
      ch = styler.SafeGetCharAt(pos);
 | 
						|
      if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z')
 | 
						|
         || (ch >= 'a' && ch <= 'z') || ch == '_') ++pos;
 | 
						|
      else break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  styler.ColourTo(pos-1, SCE_P_NUMBER);
 | 
						|
  return pos;
 | 
						|
}
 | 
						|
 | 
						|
/* rewritten from scratch, because I couldn't get rid of the bugs...
 | 
						|
   (A character based approach sucks!)
 | 
						|
*/
 | 
						|
static void ColouriseNimrodDoc(Sci_PositionU startPos, Sci_Position length, int initStyle,
 | 
						|
                                WordList *keywordlists[], Accessor &styler) {
 | 
						|
  Sci_Position pos = startPos;
 | 
						|
  Sci_Position max = startPos + length;
 | 
						|
  char ch;
 | 
						|
  WordList &keywords = *keywordlists[0];
 | 
						|
 | 
						|
  styler.StartAt(startPos);
 | 
						|
  styler.StartSegment(startPos);
 | 
						|
 | 
						|
  switch (initStyle) {
 | 
						|
    /* check where we are: */
 | 
						|
    case SCE_P_TRIPLEDOUBLE:
 | 
						|
      pos = tillEndOfTripleQuote(styler, pos, max);
 | 
						|
      styler.ColourTo(pos, SCE_P_TRIPLEDOUBLE);
 | 
						|
      pos++;
 | 
						|
    break;
 | 
						|
    default: /* nothing to do: */
 | 
						|
    break;
 | 
						|
  }
 | 
						|
  while (pos < max) {
 | 
						|
    ch = styler.SafeGetCharAt(pos, '\0');
 | 
						|
    switch (ch) {
 | 
						|
      case '\0': return;
 | 
						|
      case '#': {
 | 
						|
        bool doccomment = (styler.SafeGetCharAt(pos+1) == '#');
 | 
						|
        while (pos < max && !isNewLine(styler.SafeGetCharAt(pos, LF))) pos++;
 | 
						|
        if (doccomment)
 | 
						|
          styler.ColourTo(pos, SCE_C_COMMENTLINEDOC);
 | 
						|
        else
 | 
						|
          styler.ColourTo(pos, SCE_P_COMMENTLINE);
 | 
						|
      } break;
 | 
						|
      case 'r': case 'R': {
 | 
						|
        if (styler.SafeGetCharAt(pos+1) == '"') {
 | 
						|
          pos = scanString(styler, pos+2, max, true);
 | 
						|
          styler.ColourTo(pos, SCE_P_STRING);
 | 
						|
          pos++;
 | 
						|
        } else {
 | 
						|
          pos = scanIdent(styler, pos, keywords);
 | 
						|
        }
 | 
						|
      } break;
 | 
						|
      case '"':
 | 
						|
        if (styler.Match(pos+1, "\"\"")) {
 | 
						|
          pos = tillEndOfTripleQuote(styler, pos+3, max);
 | 
						|
          styler.ColourTo(pos, SCE_P_TRIPLEDOUBLE);
 | 
						|
        } else {
 | 
						|
          pos = scanString(styler, pos+1, max, false);
 | 
						|
          styler.ColourTo(pos, SCE_P_STRING);
 | 
						|
        }
 | 
						|
        pos++;
 | 
						|
      break;
 | 
						|
      case '\'':
 | 
						|
        pos = scanChar(styler, pos+1, max);
 | 
						|
        styler.ColourTo(pos, SCE_P_CHARACTER);
 | 
						|
        pos++;
 | 
						|
      break;
 | 
						|
      default: // identifers, numbers, operators, whitespace
 | 
						|
        if (ch >= '0' && ch <= '9') {
 | 
						|
          pos = scanNumber(styler, pos);
 | 
						|
        } else if (IsAWordChar(ch)) {
 | 
						|
          pos = scanIdent(styler, pos, keywords);
 | 
						|
        } else if (ch == '`') {
 | 
						|
          pos++;
 | 
						|
          while (pos < max) {
 | 
						|
            ch = styler.SafeGetCharAt(pos, LF);
 | 
						|
            if (ch == '`') {
 | 
						|
              ++pos;
 | 
						|
              break;
 | 
						|
            }
 | 
						|
            if (ch == CR || ch == LF) break;
 | 
						|
            ++pos;
 | 
						|
          }
 | 
						|
          styler.ColourTo(pos, SCE_P_IDENTIFIER);
 | 
						|
        } else if (strchr("()[]{}:=;-\\/&%$!+<>|^?,.*~@", ch)) {
 | 
						|
          styler.ColourTo(pos, SCE_P_OPERATOR);
 | 
						|
          pos++;
 | 
						|
        } else {
 | 
						|
          styler.ColourTo(pos, SCE_P_DEFAULT);
 | 
						|
          pos++;
 | 
						|
        }
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
static bool IsCommentLine(Sci_Position line, Accessor &styler) {
 | 
						|
	Sci_Position pos = styler.LineStart(line);
 | 
						|
	Sci_Position eol_pos = styler.LineStart(line + 1) - 1;
 | 
						|
	for (Sci_Position i = pos; i < eol_pos; i++) {
 | 
						|
		char ch = styler[i];
 | 
						|
		if (ch == '#')
 | 
						|
			return true;
 | 
						|
		else if (ch != ' ' && ch != '\t')
 | 
						|
			return false;
 | 
						|
	}
 | 
						|
	return false;
 | 
						|
}
 | 
						|
 | 
						|
static bool IsQuoteLine(Sci_Position line, Accessor &styler) {
 | 
						|
	int style = styler.StyleAt(styler.LineStart(line)) & 31;
 | 
						|
	return ((style == SCE_P_TRIPLE) || (style == SCE_P_TRIPLEDOUBLE));
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static void FoldNimrodDoc(Sci_PositionU startPos, Sci_Position length,
 | 
						|
                          int /*initStyle - unused*/,
 | 
						|
                          WordList *[], Accessor &styler) {
 | 
						|
	const Sci_Position maxPos = startPos + length;
 | 
						|
	const Sci_Position maxLines = styler.GetLine(maxPos - 1); // Requested last line
 | 
						|
	const Sci_Position docLines = styler.GetLine(styler.Length() - 1); // Available last line
 | 
						|
	const bool foldComment = styler.GetPropertyInt("fold.comment.nimrod") != 0;
 | 
						|
	const bool foldQuotes = styler.GetPropertyInt("fold.quotes.nimrod") != 0;
 | 
						|
 | 
						|
	// Backtrack to previous non-blank line so we can determine indent level
 | 
						|
	// for any white space lines (needed esp. within triple quoted strings)
 | 
						|
	// and so we can fix any preceding fold level (which is why we go back
 | 
						|
	// at least one line in all cases)
 | 
						|
	int spaceFlags = 0;
 | 
						|
	Sci_Position lineCurrent = styler.GetLine(startPos);
 | 
						|
	int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL);
 | 
						|
	while (lineCurrent > 0) {
 | 
						|
		lineCurrent--;
 | 
						|
		indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL);
 | 
						|
		if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG) &&
 | 
						|
		        (!IsCommentLine(lineCurrent, styler)) &&
 | 
						|
		        (!IsQuoteLine(lineCurrent, styler)))
 | 
						|
			break;
 | 
						|
	}
 | 
						|
	int indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK;
 | 
						|
 | 
						|
	// Set up initial loop state
 | 
						|
	startPos = styler.LineStart(lineCurrent);
 | 
						|
	int prev_state = SCE_P_DEFAULT & 31;
 | 
						|
	if (lineCurrent >= 1)
 | 
						|
		prev_state = styler.StyleAt(startPos - 1) & 31;
 | 
						|
	int prevQuote = foldQuotes && ((prev_state == SCE_P_TRIPLE) ||
 | 
						|
	                               (prev_state == SCE_P_TRIPLEDOUBLE));
 | 
						|
	int prevComment = 0;
 | 
						|
	if (lineCurrent >= 1)
 | 
						|
		prevComment = foldComment && IsCommentLine(lineCurrent - 1, styler);
 | 
						|
 | 
						|
	// Process all characters to end of requested range or end of any triple quote
 | 
						|
	// or comment that hangs over the end of the range.  Cap processing in all cases
 | 
						|
	// to end of document (in case of unclosed quote or comment at end).
 | 
						|
	while ((lineCurrent <= docLines) && ((lineCurrent <= maxLines) ||
 | 
						|
	                                      prevQuote || prevComment)) {
 | 
						|
 | 
						|
		// Gather info
 | 
						|
		int lev = indentCurrent;
 | 
						|
		Sci_Position lineNext = lineCurrent + 1;
 | 
						|
		int indentNext = indentCurrent;
 | 
						|
		int quote = false;
 | 
						|
		if (lineNext <= docLines) {
 | 
						|
			// Information about next line is only available if not at end of document
 | 
						|
			indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL);
 | 
						|
			int style = styler.StyleAt(styler.LineStart(lineNext)) & 31;
 | 
						|
			quote = foldQuotes && ((style == SCE_P_TRIPLE) || (style == SCE_P_TRIPLEDOUBLE));
 | 
						|
		}
 | 
						|
		const int quote_start = (quote && !prevQuote);
 | 
						|
		const int quote_continue = (quote && prevQuote);
 | 
						|
		const int comment = foldComment && IsCommentLine(lineCurrent, styler);
 | 
						|
		const int comment_start = (comment && !prevComment && (lineNext <= docLines) &&
 | 
						|
		                           IsCommentLine(lineNext, styler) &&
 | 
						|
		                           (lev > SC_FOLDLEVELBASE));
 | 
						|
		const int comment_continue = (comment && prevComment);
 | 
						|
		if ((!quote || !prevQuote) && !comment)
 | 
						|
			indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK;
 | 
						|
		if (quote)
 | 
						|
			indentNext = indentCurrentLevel;
 | 
						|
		if (indentNext & SC_FOLDLEVELWHITEFLAG)
 | 
						|
			indentNext = SC_FOLDLEVELWHITEFLAG | indentCurrentLevel;
 | 
						|
 | 
						|
		if (quote_start) {
 | 
						|
			// Place fold point at start of triple quoted string
 | 
						|
			lev |= SC_FOLDLEVELHEADERFLAG;
 | 
						|
		} else if (quote_continue || prevQuote) {
 | 
						|
			// Add level to rest of lines in the string
 | 
						|
			lev = lev + 1;
 | 
						|
		} else if (comment_start) {
 | 
						|
			// Place fold point at start of a block of comments
 | 
						|
			lev |= SC_FOLDLEVELHEADERFLAG;
 | 
						|
		} else if (comment_continue) {
 | 
						|
			// Add level to rest of lines in the block
 | 
						|
			lev = lev + 1;
 | 
						|
		}
 | 
						|
 | 
						|
		// Skip past any blank lines for next indent level info; we skip also
 | 
						|
		// comments (all comments, not just those starting in column 0)
 | 
						|
		// which effectively folds them into surrounding code rather
 | 
						|
		// than screwing up folding.
 | 
						|
 | 
						|
		while (!quote &&
 | 
						|
		        (lineNext < docLines) &&
 | 
						|
		        ((indentNext & SC_FOLDLEVELWHITEFLAG) ||
 | 
						|
		         (lineNext <= docLines && IsCommentLine(lineNext, styler)))) {
 | 
						|
 | 
						|
			lineNext++;
 | 
						|
			indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL);
 | 
						|
		}
 | 
						|
 | 
						|
		const int levelAfterComments = indentNext & SC_FOLDLEVELNUMBERMASK;
 | 
						|
		const int levelBeforeComments =
 | 
						|
		    Maximum(indentCurrentLevel,levelAfterComments);
 | 
						|
 | 
						|
		// Now set all the indent levels on the lines we skipped
 | 
						|
		// Do this from end to start.  Once we encounter one line
 | 
						|
		// which is indented more than the line after the end of
 | 
						|
		// the comment-block, use the level of the block before
 | 
						|
 | 
						|
		Sci_Position skipLine = lineNext;
 | 
						|
		int skipLevel = levelAfterComments;
 | 
						|
 | 
						|
		while (--skipLine > lineCurrent) {
 | 
						|
			int skipLineIndent = styler.IndentAmount(skipLine, &spaceFlags, NULL);
 | 
						|
 | 
						|
			if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments)
 | 
						|
				skipLevel = levelBeforeComments;
 | 
						|
 | 
						|
			int whiteFlag = skipLineIndent & SC_FOLDLEVELWHITEFLAG;
 | 
						|
 | 
						|
			styler.SetLevel(skipLine, skipLevel | whiteFlag);
 | 
						|
		}
 | 
						|
 | 
						|
		// Set fold header on non-quote/non-comment line
 | 
						|
		if (!quote && !comment && !(indentCurrent & SC_FOLDLEVELWHITEFLAG) ) {
 | 
						|
			if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) <
 | 
						|
			     (indentNext & SC_FOLDLEVELNUMBERMASK))
 | 
						|
				lev |= SC_FOLDLEVELHEADERFLAG;
 | 
						|
		}
 | 
						|
 | 
						|
		// Keep track of triple quote and block comment state of previous line
 | 
						|
		prevQuote = quote;
 | 
						|
		prevComment = comment_start || comment_continue;
 | 
						|
 | 
						|
		// Set fold level for this line and move to next line
 | 
						|
		styler.SetLevel(lineCurrent, lev);
 | 
						|
		indentCurrent = indentNext;
 | 
						|
		lineCurrent = lineNext;
 | 
						|
	}
 | 
						|
 | 
						|
	// NOTE: Cannot set level of last line here because indentCurrent doesn't have
 | 
						|
	// header flag set; the loop above is crafted to take care of this case!
 | 
						|
	//styler.SetLevel(lineCurrent, indentCurrent);
 | 
						|
}
 | 
						|
 | 
						|
static const char * const nimrodWordListDesc[] = {
 | 
						|
	"Keywords",
 | 
						|
	0
 | 
						|
};
 | 
						|
 | 
						|
LexerModule lmNimrod(SCLEX_NIMROD, ColouriseNimrodDoc, "nimrod", FoldNimrodDoc,
 | 
						|
				     nimrodWordListDesc);
 |