// Scintilla source code edit control // Encoding: UTF-8 /** @file LexMMIXAL.cxx ** Lexer for MMIX Assembler Language. ** Written by Christoph Hösler ** For information about MMIX visit http://www-cs-faculty.stanford.edu/~knuth/mmix.html **/ // Copyright 1998-2003 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. #include #include #include #include #include #include #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 Scintilla; static inline bool IsAWordChar(const int ch) { return (ch < 0x80) && (isalnum(ch) || ch == ':' || ch == '_'); } inline bool isMMIXALOperator(char ch) { if (IsASCII(ch) && isalnum(ch)) return false; if (ch == '+' || ch == '-' || ch == '|' || ch == '^' || ch == '*' || ch == '/' || ch == '%' || ch == '<' || ch == '>' || ch == '&' || ch == '~' || ch == '$' || ch == ',' || ch == '(' || ch == ')' || ch == '[' || ch == ']') return true; return false; } static void ColouriseMMIXALDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordlists[], Accessor &styler) { WordList &opcodes = *keywordlists[0]; WordList &special_register = *keywordlists[1]; WordList &predef_symbols = *keywordlists[2]; StyleContext sc(startPos, length, initStyle, styler); for (; sc.More(); sc.Forward()) { // No EOL continuation if (sc.atLineStart) { if (sc.ch == '@' && sc.chNext == 'i') { sc.SetState(SCE_MMIXAL_INCLUDE); } else { sc.SetState(SCE_MMIXAL_LEADWS); } } // Check if first non whitespace character in line is alphanumeric if (sc.state == SCE_MMIXAL_LEADWS && !isspace(sc.ch)) { // LEADWS if(!IsAWordChar(sc.ch)) { sc.SetState(SCE_MMIXAL_COMMENT); } else { if(sc.atLineStart) { sc.SetState(SCE_MMIXAL_LABEL); } else { sc.SetState(SCE_MMIXAL_OPCODE_PRE); } } } // Determine if the current state should terminate. if (sc.state == SCE_MMIXAL_OPERATOR) { // OPERATOR sc.SetState(SCE_MMIXAL_OPERANDS); } else if (sc.state == SCE_MMIXAL_NUMBER) { // NUMBER if (!isdigit(sc.ch)) { if (IsAWordChar(sc.ch)) { char s[100]; sc.GetCurrent(s, sizeof(s)); sc.ChangeState(SCE_MMIXAL_REF); sc.SetState(SCE_MMIXAL_REF); } else { sc.SetState(SCE_MMIXAL_OPERANDS); } } } else if (sc.state == SCE_MMIXAL_LABEL) { // LABEL if (!IsAWordChar(sc.ch) ) { sc.SetState(SCE_MMIXAL_OPCODE_PRE); } } else if (sc.state == SCE_MMIXAL_REF) { // REF if (!IsAWordChar(sc.ch) ) { char s[100]; sc.GetCurrent(s, sizeof(s)); if (*s == ':') { // ignore base prefix for match for (size_t i = 0; i != sizeof(s); ++i) { *(s+i) = *(s+i+1); } } if (special_register.InList(s)) { sc.ChangeState(SCE_MMIXAL_REGISTER); } else if (predef_symbols.InList(s)) { sc.ChangeState(SCE_MMIXAL_SYMBOL); } sc.SetState(SCE_MMIXAL_OPERANDS); } } else if (sc.state == SCE_MMIXAL_OPCODE_PRE) { // OPCODE_PRE if (!isspace(sc.ch)) { sc.SetState(SCE_MMIXAL_OPCODE); } } else if (sc.state == SCE_MMIXAL_OPCODE) { // OPCODE if (!IsAWordChar(sc.ch) ) { char s[100]; sc.GetCurrent(s, sizeof(s)); if (opcodes.InList(s)) { sc.ChangeState(SCE_MMIXAL_OPCODE_VALID); } else { sc.ChangeState(SCE_MMIXAL_OPCODE_UNKNOWN); } sc.SetState(SCE_MMIXAL_OPCODE_POST); } } else if (sc.state == SCE_MMIXAL_STRING) { // STRING if (sc.ch == '\"') { sc.ForwardSetState(SCE_MMIXAL_OPERANDS); } else if (sc.atLineEnd) { sc.ForwardSetState(SCE_MMIXAL_OPERANDS); } } else if (sc.state == SCE_MMIXAL_CHAR) { // CHAR if (sc.ch == '\'') { sc.ForwardSetState(SCE_MMIXAL_OPERANDS); } else if (sc.atLineEnd) { sc.ForwardSetState(SCE_MMIXAL_OPERANDS); } } else if (sc.state == SCE_MMIXAL_REGISTER) { // REGISTER if (!isdigit(sc.ch)) { sc.SetState(SCE_MMIXAL_OPERANDS); } } else if (sc.state == SCE_MMIXAL_HEX) { // HEX if (!isxdigit(sc.ch)) { sc.SetState(SCE_MMIXAL_OPERANDS); } } // Determine if a new state should be entered. if (sc.state == SCE_MMIXAL_OPCODE_POST || // OPCODE_POST sc.state == SCE_MMIXAL_OPERANDS) { // OPERANDS if (sc.state == SCE_MMIXAL_OPERANDS && isspace(sc.ch)) { if (!sc.atLineEnd) { sc.SetState(SCE_MMIXAL_COMMENT); } } else if (isdigit(sc.ch)) { sc.SetState(SCE_MMIXAL_NUMBER); } else if (IsAWordChar(sc.ch) || sc.Match('@')) { sc.SetState(SCE_MMIXAL_REF); } else if (sc.Match('\"')) { sc.SetState(SCE_MMIXAL_STRING); } else if (sc.Match('\'')) { sc.SetState(SCE_MMIXAL_CHAR); } else if (sc.Match('$')) { sc.SetState(SCE_MMIXAL_REGISTER); } else if (sc.Match('#')) { sc.SetState(SCE_MMIXAL_HEX); } else if (isMMIXALOperator(static_cast(sc.ch))) { sc.SetState(SCE_MMIXAL_OPERATOR); } } } sc.Complete(); } static const char * const MMIXALWordListDesc[] = { "Operation Codes", "Special Register", "Predefined Symbols", 0 }; LexerModule lmMMIXAL(SCLEX_MMIXAL, ColouriseMMIXALDoc, "mmixal", 0, MMIXALWordListDesc);