aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/SciLexer.h21
-rw-r--r--include/Scintilla.iface21
-rw-r--r--src/LexAda.cxx674
3 files changed, 533 insertions, 183 deletions
diff --git a/include/SciLexer.h b/include/SciLexer.h
index 26d559902..390ab4ef2 100644
--- a/include/SciLexer.h
+++ b/include/SciLexer.h
@@ -319,14 +319,19 @@
#define SCE_AVE_IDENTIFIER 9
#define SCE_AVE_OPERATOR 10
#define SCE_ADA_DEFAULT 0
-#define SCE_ADA_COMMENT 1
-#define SCE_ADA_NUMBER 2
-#define SCE_ADA_WORD 3
-#define SCE_ADA_STRING 4
-#define SCE_ADA_CHARACTER 5
-#define SCE_ADA_OPERATOR 6
-#define SCE_ADA_IDENTIFIER 7
-#define SCE_ADA_STRINGEOL 8
+#define SCE_ADA_WORD 1
+#define SCE_ADA_IDENTIFIER 2
+#define SCE_ADA_BADIDENTIFIER 3
+#define SCE_ADA_NUMBER 4
+#define SCE_ADA_BADNUMBER 5
+#define SCE_ADA_DELIMITER 6
+#define SCE_ADA_CHARACTER 7
+#define SCE_ADA_CHARACTEREOL 8
+#define SCE_ADA_STRING 9
+#define SCE_ADA_STRINGEOL 10
+#define SCE_ADA_LABEL 11
+#define SCE_ADA_BADLABEL 12
+#define SCE_ADA_COMMENTLINE 13
#define SCE_BAAN_DEFAULT 0
#define SCE_BAAN_COMMENT 1
#define SCE_BAAN_COMMENTDOC 2
diff --git a/include/Scintilla.iface b/include/Scintilla.iface
index 7957b64a1..b592fd062 100644
--- a/include/Scintilla.iface
+++ b/include/Scintilla.iface
@@ -1779,14 +1779,19 @@ val SCE_AVE_OPERATOR=10
# Lexical states for SCLEX_ADA
lex Ada=SCLEX_ADA SCE_ADA_
val SCE_ADA_DEFAULT=0
-val SCE_ADA_COMMENT=1
-val SCE_ADA_NUMBER=2
-val SCE_ADA_WORD=3
-val SCE_ADA_STRING=4
-val SCE_ADA_CHARACTER=5
-val SCE_ADA_OPERATOR=6
-val SCE_ADA_IDENTIFIER=7
-val SCE_ADA_STRINGEOL=8
+val SCE_ADA_WORD=1
+val SCE_ADA_IDENTIFIER=2
+val SCE_ADA_BADIDENTIFIER=3
+val SCE_ADA_NUMBER=4
+val SCE_ADA_BADNUMBER=5
+val SCE_ADA_DELIMITER=6
+val SCE_ADA_CHARACTER=7
+val SCE_ADA_CHARACTEREOL=8
+val SCE_ADA_STRING=9
+val SCE_ADA_STRINGEOL=10
+val SCE_ADA_LABEL=11
+val SCE_ADA_BADLABEL=12
+val SCE_ADA_COMMENTLINE=13
# Lexical states for SCLEX_BAAN
lex Baan=SCLEX_BAAN SCE_BAAN_
val SCE_BAAN_DEFAULT=0
diff --git a/src/LexAda.cxx b/src/LexAda.cxx
index 0d8fb9d5d..657218eef 100644
--- a/src/LexAda.cxx
+++ b/src/LexAda.cxx
@@ -1,198 +1,538 @@
-// SciTE - Scintilla based Text Editor
-// LexAda.cxx - lexer for Ada95
-// by Tahir Karaca <tahir@bigfoot.de>
-// 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 <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <stdarg.h>
-
-#include "Platform.h"
-
-#include "PropSet.h"
#include "Accessor.h"
+#include "StyleContext.h"
+#include "PropSet.h"
#include "KeyWords.h"
-#include "Scintilla.h"
#include "SciLexer.h"
+#include "SString.h"
+
+/*
+ * Interface
+ */
+
+static void ColouriseDocument(
+ unsigned int startPos,
+ int length,
+ int initStyle,
+ WordList *keywordlists[],
+ Accessor &styler);
+
+LexerModule lmAda(SCLEX_ADA, ColouriseDocument, "ada");
+
+/*
+ * Implementation
+ */
+
+static void ColouriseCharacter (StyleContext& sc);
+static void ColouriseContext (StyleContext& sc, char chEnd, int stateEOL);
+static void ColouriseComment (StyleContext& sc);
+static void ColouriseDelimiter (StyleContext& sc);
+static void ColouriseLabel (StyleContext& sc, WordList& keywords);
+static void ColouriseNumber (StyleContext& sc);
+static void ColouriseString (StyleContext& sc);
+static void ColouriseWhiteSpace (StyleContext& sc);
+static void ColouriseWord (StyleContext& sc, WordList& keywords);
-inline void classifyWordAda(unsigned int start, unsigned int end,
- WordList &keywords, Accessor &styler) {
+static inline bool isDelimiterCharacter (int ch);
+static inline bool isNumberStartCharacter (int ch);
+static inline bool isNumberCharacter (int ch);
+static inline bool isSeparatorOrDelimiter (int ch);
+static bool isValidIdentifier (const SString& identifier);
+static bool isValidNumber (const SString& number);
+static inline bool isWordStartCharacter (int ch);
+static inline bool isWordCharacter (int ch);
- static const unsigned KEWORD_LEN_MAX = 30;
+static void ColouriseCharacter (StyleContext& sc)
+{
+ sc.SetState (SCE_ADA_CHARACTER);
+
+ // Skip the apostrophe and one more character (so that '' is shown as non-terminated and '''
+ // is handled correctly)
+ sc.Forward ();
+ sc.Forward ();
+
+ ColouriseContext (sc, '\'', SCE_ADA_CHARACTEREOL);
+}
+
+static void ColouriseContext (StyleContext& sc, char chEnd, int stateEOL)
+{
+ while (!sc.atLineEnd && !sc.Match (chEnd))
+ {
+ sc.Forward ();
+ }
- char wordLower[KEWORD_LEN_MAX + 1];
- unsigned i;
- for(i = 0; ( i < KEWORD_LEN_MAX ) && ( i < end - start + 1 ); i++) {
- wordLower[i] = static_cast<char>(tolower(styler[start + i]));
+ if (!sc.atLineEnd)
+ {
+ sc.ForwardSetState (SCE_ADA_DEFAULT);
}
- wordLower[i] = '\0';
+ else
+ {
+ sc.ChangeState (stateEOL);
+ }
+}
+
+static void ColouriseComment (StyleContext& sc)
+{
+ sc.SetState (SCE_ADA_COMMENTLINE);
+
+ while (!sc.atLineEnd)
+ {
+ sc.Forward ();
+ }
+}
+
+static void ColouriseDelimiter (StyleContext& sc)
+{
+ sc.SetState (SCE_ADA_DELIMITER);
+ sc.ForwardSetState (SCE_ADA_DEFAULT);
+}
+
+static void ColouriseLabel (StyleContext& sc, WordList& keywords)
+{
+ sc.SetState (SCE_ADA_LABEL);
+
+ // Skip "<<"
+ sc.Forward ();
+ sc.Forward ();
+
+ SString identifier;
+
+ while (!sc.atLineEnd && !isSeparatorOrDelimiter (sc.ch))
+ {
+ identifier += (char) tolower (sc.ch);
+ sc.Forward ();
+ }
+
+ // Skip ">>"
+ if (sc.Match ('>', '>'))
+ {
+ sc.Forward ();
+ sc.Forward ();
+ }
+ else
+ {
+ sc.ChangeState (SCE_ADA_BADLABEL);
+ }
+
+ if (!isValidIdentifier (identifier) || keywords.InList (identifier.c_str ()))
+ {
+ sc.ChangeState (SCE_ADA_BADLABEL);
+ }
+
+ sc.SetState (SCE_ADA_DEFAULT);
+}
+
+static void ColouriseNumber (StyleContext& sc)
+{
+ SString number;
+ sc.SetState (SCE_ADA_NUMBER);
+
+ while (!isSeparatorOrDelimiter (sc.ch))
+ {
+ number += (char) sc.ch;
+ sc.Forward ();
+ }
+
+ // Special case: exponent with sign
+ if (tolower (sc.chPrev) == 'e'
+ && (sc.Match ('+') || sc.Match ('-'))
+ && isdigit (sc.chNext))
+ {
+ number += (char) sc.ch;
+ sc.Forward ();
-// int levelChange = 0;
- char chAttr = SCE_ADA_IDENTIFIER;
- if (keywords.InList(wordLower)) {
- chAttr = SCE_ADA_WORD;
-
-// Folding doesn't work this way since the semantics of some keywords depends
-// on the current context.
-// E.g. - "cond1 and THEN cond2" <-> "if ... THEN ..."
-// - "procedure X IS ... end X;" <-> "procedure X IS new Y;"
-// if (strcmp(wordLower, "is") == 0 || strcmp(wordLower, "then") == 0)
-// levelChange=1;
-// else if (strcmp(wordLower, "end") == 0)
-// levelChange=-1;
- }
- styler.ColourTo(end, chAttr);
+ while (!isSeparatorOrDelimiter (sc.ch))
+ {
+ number += (char) sc.ch;
+ sc.Forward ();
+ }
+ }
-// return levelChange;
+ if (!isValidNumber (number))
+ {
+ sc.ChangeState (SCE_ADA_BADNUMBER);
+ }
+
+ sc.SetState (SCE_ADA_DEFAULT);
}
+static void ColouriseString (StyleContext& sc)
+{
+ sc.SetState (SCE_ADA_STRING);
+ sc.Forward ();
-static inline bool isAdaOperator(char ch) {
-
- if (ch == '&' || ch == '\'' || ch == '(' || ch == ')' ||
- ch == '*' || ch == '+' || ch == ',' || ch == '-' ||
- ch == '.' || ch == '/' || ch == ':' || ch == ';' ||
- ch == '<' || ch == '=' || ch == '>')
- return true;
- return false;
+ ColouriseContext (sc, '"', SCE_ADA_STRINGEOL);
}
+static void ColouriseWhiteSpace (StyleContext& sc)
+{
+ sc.SetState (SCE_ADA_DEFAULT);
+ sc.ForwardSetState (SCE_ADA_DEFAULT);
+}
-inline void styleTokenBegin(char beginChar, unsigned int pos, int &state,
- Accessor &styler) {
-
- if (isalpha(beginChar)) {
- styler.ColourTo(pos-1, state);
- state = SCE_ADA_IDENTIFIER;
- } else if (isdigit(beginChar)) {
- styler.ColourTo(pos-1, state);
- state = SCE_ADA_NUMBER;
- } else if (beginChar == '-' && styler.SafeGetCharAt(pos + 1) == '-') {
- styler.ColourTo(pos-1, state);
- state = SCE_ADA_COMMENT;
- } else if (beginChar == '\"') {
- styler.ColourTo(pos-1, state);
- state = SCE_ADA_STRING;
- } else if (beginChar == '\'' && styler.SafeGetCharAt(pos + 2) == '\'') {
- styler.ColourTo(pos-1, state);
- state = SCE_ADA_CHARACTER;
- } else if (isAdaOperator(beginChar)) {
- styler.ColourTo(pos-1, state);
- styler.ColourTo(pos, SCE_ADA_OPERATOR);
- }
-}
-
-
-static void ColouriseAdaDoc(unsigned int startPos, int length, int initStyle,
- WordList *keywordlists[], Accessor &styler) {
+static void ColouriseWord (StyleContext& sc, WordList& keywords)
+{
+ SString identifier;
+ sc.SetState (SCE_ADA_IDENTIFIER);
+
+ while (!sc.atLineEnd && isWordCharacter (sc.ch))
+ {
+ identifier += (char) tolower (sc.ch);
+ sc.Forward ();
+ }
+
+ if (!isValidIdentifier (identifier))
+ {
+ sc.ChangeState (SCE_ADA_BADIDENTIFIER);
+ }
+ else if (keywords.InList (identifier.c_str ()))
+ {
+ sc.ChangeState (SCE_ADA_WORD);
+ }
+ sc.SetState (SCE_ADA_DEFAULT);
+}
+
+//
+// ColouriseDocument
+//
+
+static void ColouriseDocument(
+ unsigned int startPos,
+ int length,
+ int initStyle,
+ WordList *keywordlists[],
+ Accessor &styler)
+{
WordList &keywords = *keywordlists[0];
+
+ StyleContext sc(startPos, length, initStyle, styler);
+
+ // Apostrophe can start either an attribute or a character constant. Which
+ int lineCurrent = styler.GetLine (startPos);
+ int lineState = styler.GetLineState (lineCurrent);
+
+ bool apostropheStartsAttribute = (lineState & 1) != 0;
+
+ while (sc.More ())
+ {
+ if (sc.atLineEnd)
+ {
+ sc.Forward ();
+ lineCurrent++;
+
+ // Remember the apostrophe setting
+ styler.SetLineState (lineCurrent, apostropheStartsAttribute ? 1 : 0);
+
+ // Don't leak any styles onto the next line
+ sc.SetState (SCE_ADA_DEFAULT);
+ }
+
+ // Comments
+ if (sc.Match ('-', '-'))
+ {
+ ColouriseComment (sc);
+ }
+
+ // Strings
+ else if (sc.Match ('"'))
+ {
+ apostropheStartsAttribute = false;
+ ColouriseString (sc);
+ }
+
+ // Characters
+ else if (sc.Match ('\'') && !apostropheStartsAttribute)
+ {
+ apostropheStartsAttribute = false;
+ ColouriseCharacter (sc);
+ }
+
+ // Labels
+ else if (sc.Match ('<', '<'))
+ {
+ apostropheStartsAttribute = false;
+ ColouriseLabel (sc, keywords);
+ }
+
+ // Whitespace
+ else if (isspace (sc.ch))
+ {
+ ColouriseWhiteSpace (sc);
+ }
+
+ // Delimiters
+ else if (isDelimiterCharacter (sc.ch))
+ {
+ apostropheStartsAttribute = sc.ch == ')';
+ ColouriseDelimiter (sc);
+ }
+
+ // Numbers
+ else if (isdigit (sc.ch))
+ {
+ apostropheStartsAttribute = false;
+ ColouriseNumber (sc);
+ }
+
+ // Keywords or identifiers
+ else
+ {
+ apostropheStartsAttribute = true;
+ ColouriseWord (sc, keywords);
+ }
+ }
+
+ 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 isdigit (ch) != 0;
+}
+
+static inline bool isSeparatorOrDelimiter (int ch)
+{
+ return isspace (ch) || isDelimiterCharacter (ch);
+}
+
+static bool isValidIdentifier (const SString& identifier)
+{
+ // First character can't be '_', so we set the variable to true initially
+ bool lastWasUnderscore = true;
+
+ int length = identifier.length ();
- styler.StartAt(startPos);
+ // Zero-length identifiers are not valid (these can occur inside labels)
+ if (length == 0) return false;
+
+ if (!isWordStartCharacter (identifier[0])) return false;
+
+ // Check for only valid characters and no double underscores
+ for (int i = 0; i < length; i++)
+ {
+ if (!isWordCharacter (identifier[i])) return false;
+ else if (identifier[i] == '_' && lastWasUnderscore) return false;
+ lastWasUnderscore = identifier[i] == '_';
+ }
+
+ // Check for underscore at the end
+ if (lastWasUnderscore == true) return false;
+
+ // All checks passed
+ return true;
+}
+
+static bool isValidNumber (const SString& number)
+{
+ int hashPos = number.search ("#");
+ bool seenDot = false;
-// bool fold = styler.GetPropertyInt("fold");
-// int lineCurrent = styler.GetLine(startPos);
-// int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
-// int levelCurrent = levelPrev;
-
- int state = initStyle;
- if (state == SCE_ADA_STRINGEOL) // Does not leak onto next line
- state = SCE_ADA_DEFAULT;
- char chNext = styler[startPos];
- const unsigned int lengthDoc = startPos + length;
- //int visibleChars = 0;
- styler.StartSegment(startPos);
- for (unsigned int i = startPos; i < lengthDoc; i++) {
- char ch = chNext;
- chNext = styler.SafeGetCharAt(i + 1);
-
- if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
- // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix)
- // Avoid triggering two times on Dos/Win
- if (state == SCE_ADA_STRINGEOL) {
- styler.ColourTo(i, state);
- state = SCE_ADA_DEFAULT;
- }
-// if (fold) {
-// int lev = levelPrev;
-// if (visibleChars == 0)
-// lev |= SC_FOLDLEVELWHITEFLAG;
-// if ((levelCurrent > levelPrev) && (visibleChars > 0))
-// lev |= SC_FOLDLEVELHEADERFLAG;
-// styler.SetLevel(lineCurrent, lev);
-// lineCurrent++;
-// levelPrev = levelCurrent;
-// }
- //visibleChars = 0;
+ int i = 0;
+ int length = number.length ();
+
+ if (length == 0) return false; // Just in case
+
+ // Decimal number
+ if (hashPos == -1)
+ {
+ bool canBeSpecial = false;
+
+ for (; i < length; i++)
+ {
+ if (number[i] == '_')
+ {
+ if (!canBeSpecial) return false;
+ canBeSpecial = false;
+ }
+ else if (number[i] == '.')
+ {
+ if (!canBeSpecial || seenDot) return false;
+ canBeSpecial = false;
+ seenDot = true;
+ }
+ else if (isdigit (number[i]))
+ {
+ canBeSpecial = true;
+ }
+ else if (number[i] != 'e' && number[i] != 'E')
+ {
+ return false;
+ }
}
- //if (!isspacechar(ch))
- // visibleChars++;
+
+ if (!canBeSpecial) return false;
+ }
+
+ // Based number
+ else
+ {
+ bool canBeSpecial = false;
+ int base = 0;
- if (styler.IsLeadByte(ch)) {
- chNext = styler.SafeGetCharAt(i + 2);
- i += 1;
- continue;
+ // Parse base
+ for (; i < length; i++)
+ {
+ int ch = number[i];
+ if (ch == '_')
+ {
+ if (!canBeSpecial) return false;
+ canBeSpecial = false;
+ }
+ else if (isdigit (ch))
+ {
+ base = base * 10 + (ch - '0');
+ if (base > 16) return false;
+ canBeSpecial = true;
+ }
+ else if (ch == '#' && canBeSpecial)
+ {
+ break;
+ }
+ else
+ {
+ return false;
+ }
}
- if (state == SCE_ADA_DEFAULT) {
- styleTokenBegin(ch, i, state, styler);
- } else if (state == SCE_ADA_IDENTIFIER) {
- if (!iswordchar(ch)) {
- classifyWordAda(styler.GetStartSegment(),
- i - 1,
- keywords,
- styler);
- state = SCE_ADA_DEFAULT;
- styleTokenBegin(ch, i, state, styler);
- }
- } else if (state == SCE_ADA_COMMENT) {
- if (ch == '\r' || ch == '\n') {
- styler.ColourTo(i-1, state);
- state = SCE_ADA_DEFAULT;
- }
- } else if (state == SCE_ADA_STRING) {
- if (ch == '"' ) {
- if( chNext == '"' ) {
- i++;
- chNext = styler.SafeGetCharAt(i + 1);
- } else {
- styler.ColourTo(i, state);
- state = SCE_ADA_DEFAULT;
- }
- } else if (chNext == '\r' || chNext == '\n') {
- styler.ColourTo(i-1, SCE_ADA_STRINGEOL);
- state = SCE_ADA_STRINGEOL;
- }
- } else if (state == SCE_ADA_CHARACTER) {
- if (ch == '\r' || ch == '\n') {
- styler.ColourTo(i-1, SCE_ADA_STRINGEOL);
- state = SCE_ADA_STRINGEOL;
- } else if (ch == '\'' && styler.SafeGetCharAt(i - 2) == '\'') {
- styler.ColourTo(i, state);
- state = SCE_ADA_DEFAULT;
- }
- } else if (state == SCE_ADA_NUMBER) {
- if ( !( isdigit(ch) || ch == '.' || ch == '_' || ch == '#'
- || ch == 'A' || ch == 'B' || ch == 'C' || ch == 'D'
- || ch == 'E' || ch == 'F'
- || ch == 'a' || ch == 'b' || ch == 'c' || ch == 'd'
- || ch == 'e' || ch == 'f' ) ) {
- styler.ColourTo(i-1, SCE_ADA_NUMBER);
- state = SCE_ADA_DEFAULT;
- styleTokenBegin(ch, i, state, styler);
+ if (base < 2) return false;
+ if (i == length) return false;
+
+ i++; // Skip over '#'
+
+ // Parse number
+ canBeSpecial = false;
+
+ for (; i < length; i++)
+ {
+ int ch = tolower (number[i]);
+ if (ch == '_')
+ {
+ if (!canBeSpecial) return false;
+ canBeSpecial = false;
+ }
+ else if (ch == '.')
+ {
+ if (!canBeSpecial || seenDot) return false;
+ canBeSpecial = false;
+ seenDot = true;
+ }
+ else if (isdigit (ch))
+ {
+ if (ch - '0' >= base) return false;
+ canBeSpecial = true;
+ }
+ else if (ch >= 'a' && ch <= 'f')
+ {
+ if (ch - 'a' + 10 >= base) return false;
+ canBeSpecial = true;
+ }
+ else if (ch == '#' && canBeSpecial)
+ {
+ break;
+ }
+ else
+ {
+ return false;
}
}
+
+ if (i == length) return false;
+ i++;
+ }
+
+ // Exponent (optional)
+ if (i < length)
+ {
+ if (number[i] != 'e' && number[i] != 'E') return false;
+
+ i++;
+
+ if (i == length) return false;
+
+ if (number[i] == '+')
+ i++;
+ else if (number[i] == '-')
+ {
+ if (seenDot)
+ i++;
+ else
+ return false; // Integer literals should not have negative exponents
+ }
+
+ if (i == length) return false;
+
+ bool canBeSpecial = false;
+ for (; i < length; i++)
+ {
+ if (number[i] == '_')
+ {
+ if (!canBeSpecial) return false;
+ canBeSpecial = false;
+ }
+ else if (isdigit (number[i]))
+ {
+ canBeSpecial = true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ if (!canBeSpecial) return false;
}
- styler.ColourTo(lengthDoc - 1, state);
-// // Fill in the real level of the next line, keeping the current flags as they will be filled in later
-// if (fold) {
-// int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
-// styler.SetLevel(lineCurrent, levelPrev | flagsNext);
-// }
+ return i == length; // if i == length, number was parsed successfully.
+}
+
+static inline bool isWordCharacter (int ch)
+{
+ return isWordStartCharacter (ch) || isdigit (ch);
}
-LexerModule lmAda(SCLEX_ADA, ColouriseAdaDoc, "ada");
+static inline bool isWordStartCharacter (int ch)
+{
+ return isalpha (ch) || ch == '_';
+}