mirror of
				https://github.com/notepad-plus-plus/notepad-plus-plus.git
				synced 2025-11-03 21:14:08 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			205 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			205 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
// Scintilla source code edit control
 | 
						|
/** @file LexSpice.cxx
 | 
						|
 ** Lexer for Spice
 | 
						|
 **/
 | 
						|
// Copyright 2006 by Fabien Proriol
 | 
						|
// 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 "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;
 | 
						|
 | 
						|
/*
 | 
						|
 * Interface
 | 
						|
 */
 | 
						|
 | 
						|
static void ColouriseDocument(
 | 
						|
    Sci_PositionU startPos,
 | 
						|
    Sci_Position length,
 | 
						|
    int initStyle,
 | 
						|
    WordList *keywordlists[],
 | 
						|
    Accessor &styler);
 | 
						|
 | 
						|
static const char * const spiceWordListDesc[] = {
 | 
						|
    "Keywords",        // SPICE command
 | 
						|
    "Keywords2",    // SPICE functions
 | 
						|
    "Keywords3",    // SPICE params
 | 
						|
    0
 | 
						|
};
 | 
						|
 | 
						|
LexerModule lmSpice(SCLEX_SPICE, ColouriseDocument, "spice", NULL, spiceWordListDesc);
 | 
						|
 | 
						|
/*
 | 
						|
 * Implementation
 | 
						|
 */
 | 
						|
 | 
						|
static void ColouriseComment(StyleContext& sc, bool& apostropheStartsAttribute);
 | 
						|
static void ColouriseDelimiter(StyleContext& sc, bool& apostropheStartsAttribute);
 | 
						|
static void ColouriseNumber(StyleContext& sc, bool& apostropheStartsAttribute);
 | 
						|
static void ColouriseWhiteSpace(StyleContext& sc, bool& apostropheStartsAttribute);
 | 
						|
static void ColouriseWord(StyleContext& sc, WordList& keywords, WordList& keywords2, WordList& keywords3, bool& apostropheStartsAttribute);
 | 
						|
 | 
						|
static inline bool IsDelimiterCharacter(int ch);
 | 
						|
static inline bool IsSeparatorOrDelimiterCharacter(int ch);
 | 
						|
 | 
						|
static void ColouriseComment(StyleContext& sc, bool&) {
 | 
						|
    sc.SetState(SCE_SPICE_COMMENTLINE);
 | 
						|
    while (!sc.atLineEnd) {
 | 
						|
        sc.Forward();
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void ColouriseDelimiter(StyleContext& sc, bool& apostropheStartsAttribute) {
 | 
						|
    apostropheStartsAttribute = sc.Match (')');
 | 
						|
    sc.SetState(SCE_SPICE_DELIMITER);
 | 
						|
    sc.ForwardSetState(SCE_SPICE_DEFAULT);
 | 
						|
}
 | 
						|
 | 
						|
static void ColouriseNumber(StyleContext& sc, bool& apostropheStartsAttribute) {
 | 
						|
    apostropheStartsAttribute = true;
 | 
						|
    std::string number;
 | 
						|
    sc.SetState(SCE_SPICE_NUMBER);
 | 
						|
    // Get all characters up to a delimiter or a separator, including points, but excluding
 | 
						|
    // double points (ranges).
 | 
						|
    while (!IsSeparatorOrDelimiterCharacter(sc.ch) || (sc.ch == '.' && sc.chNext != '.')) {
 | 
						|
        number += static_cast<char>(sc.ch);
 | 
						|
        sc.Forward();
 | 
						|
    }
 | 
						|
    // Special case: exponent with sign
 | 
						|
    if ((sc.chPrev == 'e' || sc.chPrev == 'E') &&
 | 
						|
            (sc.ch == '+' || sc.ch == '-')) {
 | 
						|
        number += static_cast<char>(sc.ch);
 | 
						|
        sc.Forward ();
 | 
						|
        while (!IsSeparatorOrDelimiterCharacter(sc.ch)) {
 | 
						|
            number += static_cast<char>(sc.ch);
 | 
						|
            sc.Forward();
 | 
						|
        }
 | 
						|
    }
 | 
						|
    sc.SetState(SCE_SPICE_DEFAULT);
 | 
						|
}
 | 
						|
 | 
						|
static void ColouriseWhiteSpace(StyleContext& sc, bool& ) {
 | 
						|
    sc.SetState(SCE_SPICE_DEFAULT);
 | 
						|
    sc.ForwardSetState(SCE_SPICE_DEFAULT);
 | 
						|
}
 | 
						|
 | 
						|
static void ColouriseWord(StyleContext& sc, WordList& keywords, WordList& keywords2, WordList& keywords3, bool& apostropheStartsAttribute) {
 | 
						|
    apostropheStartsAttribute = true;
 | 
						|
    sc.SetState(SCE_SPICE_IDENTIFIER);
 | 
						|
    std::string word;
 | 
						|
    while (!sc.atLineEnd && !IsSeparatorOrDelimiterCharacter(sc.ch)) {
 | 
						|
        word += static_cast<char>(tolower(sc.ch));
 | 
						|
        sc.Forward();
 | 
						|
    }
 | 
						|
    if (keywords.InList(word.c_str())) {
 | 
						|
        sc.ChangeState(SCE_SPICE_KEYWORD);
 | 
						|
        if (word != "all") {
 | 
						|
            apostropheStartsAttribute = false;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    else if (keywords2.InList(word.c_str())) {
 | 
						|
        sc.ChangeState(SCE_SPICE_KEYWORD2);
 | 
						|
        if (word != "all") {
 | 
						|
            apostropheStartsAttribute = false;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    else if (keywords3.InList(word.c_str())) {
 | 
						|
        sc.ChangeState(SCE_SPICE_KEYWORD3);
 | 
						|
        if (word != "all") {
 | 
						|
            apostropheStartsAttribute = false;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    sc.SetState(SCE_SPICE_DEFAULT);
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// ColouriseDocument
 | 
						|
//
 | 
						|
static void ColouriseDocument(
 | 
						|
    Sci_PositionU startPos,
 | 
						|
    Sci_Position length,
 | 
						|
    int initStyle,
 | 
						|
    WordList *keywordlists[],
 | 
						|
    Accessor &styler) {
 | 
						|
    WordList &keywords = *keywordlists[0];
 | 
						|
    WordList &keywords2 = *keywordlists[1];
 | 
						|
    WordList &keywords3 = *keywordlists[2];
 | 
						|
    StyleContext sc(startPos, length, initStyle, styler);
 | 
						|
    Sci_Position lineCurrent = styler.GetLine(startPos);
 | 
						|
    bool apostropheStartsAttribute = (styler.GetLineState(lineCurrent) & 1) != 0;
 | 
						|
    while (sc.More()) {
 | 
						|
        if (sc.atLineEnd) {
 | 
						|
            // Go to the next line
 | 
						|
            sc.Forward();
 | 
						|
            lineCurrent++;
 | 
						|
            // Remember the line state for future incremental lexing
 | 
						|
            styler.SetLineState(lineCurrent, apostropheStartsAttribute);
 | 
						|
            // Don't continue any styles on the next line
 | 
						|
            sc.SetState(SCE_SPICE_DEFAULT);
 | 
						|
        }
 | 
						|
        // Comments
 | 
						|
        if ((sc.Match('*') && sc.atLineStart) || sc.Match('*','~')) {
 | 
						|
            ColouriseComment(sc, apostropheStartsAttribute);
 | 
						|
        // Whitespace
 | 
						|
        } else if (IsASpace(sc.ch)) {
 | 
						|
            ColouriseWhiteSpace(sc, apostropheStartsAttribute);
 | 
						|
        // Delimiters
 | 
						|
        } else if (IsDelimiterCharacter(sc.ch)) {
 | 
						|
            ColouriseDelimiter(sc, apostropheStartsAttribute);
 | 
						|
        // Numbers
 | 
						|
        } else if (IsADigit(sc.ch) || sc.ch == '#') {
 | 
						|
            ColouriseNumber(sc, apostropheStartsAttribute);
 | 
						|
        // Keywords or identifiers
 | 
						|
        } else {
 | 
						|
            ColouriseWord(sc, keywords, keywords2, keywords3, apostropheStartsAttribute);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    sc.Complete();
 | 
						|
}
 | 
						|
 | 
						|
static inline bool IsDelimiterCharacter(int ch) {
 | 
						|
    switch (ch) {
 | 
						|
    case '&':
 | 
						|
    case '\'':
 | 
						|
    case '(':
 | 
						|
    case ')':
 | 
						|
    case '*':
 | 
						|
    case '+':
 | 
						|
    case ',':
 | 
						|
    case '-':
 | 
						|
    case '.':
 | 
						|
    case '/':
 | 
						|
    case ':':
 | 
						|
    case ';':
 | 
						|
    case '<':
 | 
						|
    case '=':
 | 
						|
    case '>':
 | 
						|
    case '|':
 | 
						|
        return true;
 | 
						|
    default:
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static inline bool IsSeparatorOrDelimiterCharacter(int ch) {
 | 
						|
    return IsASpace(ch) || IsDelimiterCharacter(ch);
 | 
						|
}
 |