summaryrefslogtreecommitdiffstats
path: root/src/LexSpice.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/LexSpice.cpp')
-rw-r--r--src/LexSpice.cpp221
1 files changed, 221 insertions, 0 deletions
diff --git a/src/LexSpice.cpp b/src/LexSpice.cpp
new file mode 100644
index 0000000..8a1683f
--- /dev/null
+++ b/src/LexSpice.cpp
@@ -0,0 +1,221 @@
+// 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 <ctype.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "Platform.h"
+
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "PropSet.h"
+#include "KeyWords.h"
+#include "SciLexer.h"
+#include "SString.h"
+
+/*
+ * Interface
+ */
+
+static void ColouriseDocument(
+ unsigned int startPos,
+ int 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 IsNumberStartCharacter(int ch);
+static inline bool IsNumberCharacter(int ch);
+static inline bool IsSeparatorOrDelimiterCharacter(int ch);
+static inline bool IsWordStartCharacter(int ch);
+static inline bool IsWordCharacter(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;
+ SString 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);
+ SString 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(
+ unsigned int startPos,
+ int 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);
+ int 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 IsNumberCharacter(int ch) {
+ return IsNumberStartCharacter(ch) ||
+ ch == '_' ||
+ ch == '.' ||
+ ch == '#' ||
+ (ch >= 'a' && ch <= 'f') ||
+ (ch >= 'A' && ch <= 'F');
+}
+
+static inline bool IsNumberStartCharacter(int ch) {
+ return IsADigit(ch);
+}
+
+static inline bool IsSeparatorOrDelimiterCharacter(int ch) {
+ return IsASpace(ch) || IsDelimiterCharacter(ch);
+}
+
+static inline bool IsWordCharacter(int ch) {
+ return IsWordStartCharacter(ch) || IsADigit(ch);
+}
+
+static inline bool IsWordStartCharacter(int ch) {
+ return (isascii(ch) && isalpha(ch)) || ch == '_';
+}