--- /dev/null
+// Scintilla source code edit control\r
+/** @file LexSpice.cxx\r
+ ** Lexer for Spice\r
+ **/\r
+// Copyright 2006 by Fabien Proriol\r
+// The License.txt file describes the conditions under which this software may be distributed.\r
+\r
+#include <stdlib.h>\r
+#include <ctype.h>\r
+#include <string.h>\r
+#include <stdio.h>\r
+\r
+#include "Platform.h"\r
+\r
+#include "Accessor.h"\r
+#include "StyleContext.h"\r
+#include "PropSet.h"\r
+#include "KeyWords.h"\r
+#include "SciLexer.h"\r
+#include "SString.h"\r
+\r
+#ifdef SCI_NAMESPACE\r
+using namespace Scintilla;\r
+#endif\r
+\r
+/*\r
+ * Interface\r
+ */\r
+\r
+static void ColouriseDocument(\r
+ unsigned int startPos,\r
+ int length,\r
+ int initStyle,\r
+ WordList *keywordlists[],\r
+ Accessor &styler);\r
+\r
+static const char * const spiceWordListDesc[] = {\r
+ "Keywords", // SPICE command\r
+ "Keywords2", // SPICE functions\r
+ "Keywords3", // SPICE params\r
+ 0\r
+};\r
+\r
+LexerModule lmSpice(SCLEX_SPICE, ColouriseDocument, "spice", NULL, spiceWordListDesc);\r
+\r
+/*\r
+ * Implementation\r
+ */\r
+\r
+static void ColouriseComment(StyleContext& sc, bool& apostropheStartsAttribute);\r
+static void ColouriseDelimiter(StyleContext& sc, bool& apostropheStartsAttribute);\r
+static void ColouriseNumber(StyleContext& sc, bool& apostropheStartsAttribute);\r
+static void ColouriseWhiteSpace(StyleContext& sc, bool& apostropheStartsAttribute);\r
+static void ColouriseWord(StyleContext& sc, WordList& keywords, WordList& keywords2, WordList& keywords3, bool& apostropheStartsAttribute);\r
+\r
+static inline bool IsDelimiterCharacter(int ch);\r
+static inline bool IsNumberStartCharacter(int ch);\r
+static inline bool IsNumberCharacter(int ch);\r
+static inline bool IsSeparatorOrDelimiterCharacter(int ch);\r
+static inline bool IsWordStartCharacter(int ch);\r
+static inline bool IsWordCharacter(int ch);\r
+\r
+static void ColouriseComment(StyleContext& sc, bool&) {\r
+ sc.SetState(SCE_SPICE_COMMENTLINE);\r
+ while (!sc.atLineEnd) {\r
+ sc.Forward();\r
+ }\r
+}\r
+\r
+static void ColouriseDelimiter(StyleContext& sc, bool& apostropheStartsAttribute) {\r
+ apostropheStartsAttribute = sc.Match (')');\r
+ sc.SetState(SCE_SPICE_DELIMITER);\r
+ sc.ForwardSetState(SCE_SPICE_DEFAULT);\r
+}\r
+\r
+static void ColouriseNumber(StyleContext& sc, bool& apostropheStartsAttribute) {\r
+ apostropheStartsAttribute = true;\r
+ SString number;\r
+ sc.SetState(SCE_SPICE_NUMBER);\r
+ // Get all characters up to a delimiter or a separator, including points, but excluding\r
+ // double points (ranges).\r
+ while (!IsSeparatorOrDelimiterCharacter(sc.ch) || (sc.ch == '.' && sc.chNext != '.')) {\r
+ number += static_cast<char>(sc.ch);\r
+ sc.Forward();\r
+ }\r
+ // Special case: exponent with sign\r
+ if ((sc.chPrev == 'e' || sc.chPrev == 'E') &&\r
+ (sc.ch == '+' || sc.ch == '-')) {\r
+ number += static_cast<char>(sc.ch);\r
+ sc.Forward ();\r
+ while (!IsSeparatorOrDelimiterCharacter(sc.ch)) {\r
+ number += static_cast<char>(sc.ch);\r
+ sc.Forward();\r
+ }\r
+ }\r
+ sc.SetState(SCE_SPICE_DEFAULT);\r
+}\r
+\r
+static void ColouriseWhiteSpace(StyleContext& sc, bool& ) {\r
+ sc.SetState(SCE_SPICE_DEFAULT);\r
+ sc.ForwardSetState(SCE_SPICE_DEFAULT);\r
+}\r
+\r
+static void ColouriseWord(StyleContext& sc, WordList& keywords, WordList& keywords2, WordList& keywords3, bool& apostropheStartsAttribute) {\r
+ apostropheStartsAttribute = true;\r
+ sc.SetState(SCE_SPICE_IDENTIFIER);\r
+ SString word;\r
+ while (!sc.atLineEnd && !IsSeparatorOrDelimiterCharacter(sc.ch)) {\r
+ word += static_cast<char>(tolower(sc.ch));\r
+ sc.Forward();\r
+ }\r
+ if (keywords.InList(word.c_str())) {\r
+ sc.ChangeState(SCE_SPICE_KEYWORD);\r
+ if (word != "all") {\r
+ apostropheStartsAttribute = false;\r
+ }\r
+ }\r
+ else if (keywords2.InList(word.c_str())) {\r
+ sc.ChangeState(SCE_SPICE_KEYWORD2);\r
+ if (word != "all") {\r
+ apostropheStartsAttribute = false;\r
+ }\r
+ }\r
+ else if (keywords3.InList(word.c_str())) {\r
+ sc.ChangeState(SCE_SPICE_KEYWORD3);\r
+ if (word != "all") {\r
+ apostropheStartsAttribute = false;\r
+ }\r
+ }\r
+ sc.SetState(SCE_SPICE_DEFAULT);\r
+}\r
+\r
+//\r
+// ColouriseDocument\r
+//\r
+static void ColouriseDocument(\r
+ unsigned int startPos,\r
+ int length,\r
+ int initStyle,\r
+ WordList *keywordlists[],\r
+ Accessor &styler) {\r
+ WordList &keywords = *keywordlists[0];\r
+ WordList &keywords2 = *keywordlists[1];\r
+ WordList &keywords3 = *keywordlists[2];\r
+ StyleContext sc(startPos, length, initStyle, styler);\r
+ int lineCurrent = styler.GetLine(startPos);\r
+ bool apostropheStartsAttribute = (styler.GetLineState(lineCurrent) & 1) != 0;\r
+ while (sc.More()) {\r
+ if (sc.atLineEnd) {\r
+ // Go to the next line\r
+ sc.Forward();\r
+ lineCurrent++;\r
+ // Remember the line state for future incremental lexing\r
+ styler.SetLineState(lineCurrent, apostropheStartsAttribute);\r
+ // Don't continue any styles on the next line\r
+ sc.SetState(SCE_SPICE_DEFAULT);\r
+ }\r
+ // Comments\r
+ if ((sc.Match('*') && sc.atLineStart) || sc.Match('*','~')) {\r
+ ColouriseComment(sc, apostropheStartsAttribute);\r
+ // Whitespace\r
+ } else if (IsASpace(sc.ch)) {\r
+ ColouriseWhiteSpace(sc, apostropheStartsAttribute);\r
+ // Delimiters\r
+ } else if (IsDelimiterCharacter(sc.ch)) {\r
+ ColouriseDelimiter(sc, apostropheStartsAttribute);\r
+ // Numbers\r
+ } else if (IsADigit(sc.ch) || sc.ch == '#') {\r
+ ColouriseNumber(sc, apostropheStartsAttribute);\r
+ // Keywords or identifiers\r
+ } else {\r
+ ColouriseWord(sc, keywords, keywords2, keywords3, apostropheStartsAttribute);\r
+ }\r
+ }\r
+ sc.Complete();\r
+}\r
+\r
+static inline bool IsDelimiterCharacter(int ch) {\r
+ switch (ch) {\r
+ case '&':\r
+ case '\'':\r
+ case '(':\r
+ case ')':\r
+ case '*':\r
+ case '+':\r
+ case ',':\r
+ case '-':\r
+ case '.':\r
+ case '/':\r
+ case ':':\r
+ case ';':\r
+ case '<':\r
+ case '=':\r
+ case '>':\r
+ case '|':\r
+ return true;\r
+ default:\r
+ return false;\r
+ }\r
+}\r
+\r
+static inline bool IsNumberCharacter(int ch) {\r
+ return IsNumberStartCharacter(ch) ||\r
+ ch == '_' ||\r
+ ch == '.' ||\r
+ ch == '#' ||\r
+ (ch >= 'a' && ch <= 'f') ||\r
+ (ch >= 'A' && ch <= 'F');\r
+}\r
+\r
+static inline bool IsNumberStartCharacter(int ch) {\r
+ return IsADigit(ch);\r
+}\r
+\r
+static inline bool IsSeparatorOrDelimiterCharacter(int ch) {\r
+ return IsASpace(ch) || IsDelimiterCharacter(ch);\r
+}\r
+\r
+static inline bool IsWordCharacter(int ch) {\r
+ return IsWordStartCharacter(ch) || IsADigit(ch);\r
+}\r
+\r
+static inline bool IsWordStartCharacter(int ch) {\r
+ return (isascii(ch) && isalpha(ch)) || ch == '_';\r
+}\r