1 // Scintilla source code edit control
2 /** @file LexAPDL.cxx
3  ** Lexer for APDL. Based on the lexer for Assembler by The Black Horus.
4  ** By Hadar Raz.
5  **/
6 // Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
7 // The License.txt file describes the conditions under which this software may be distributed.
8 
9 #include <stdlib.h>
10 #include <string.h>
11 #include <ctype.h>
12 #include <stdio.h>
13 #include <stdarg.h>
14 
15 #include "Platform.h"
16 
17 #include "PropSet.h"
18 #include "Accessor.h"
19 #include "StyleContext.h"
20 #include "KeyWords.h"
21 #include "Scintilla.h"
22 #include "SciLexer.h"
23 
24 
IsAWordChar(const int ch)25 static inline bool IsAWordChar(const int ch) {
26 	return (ch < 0x80 && (isalnum(ch) || ch == '_'));
27 }
28 
IsAnOperator(char ch)29 static inline bool IsAnOperator(char ch) {
30 	// '.' left out as it is used to make up numbers
31 	if (ch == '*' || ch == '/' || ch == '-' || ch == '+' ||
32 		ch == '(' || ch == ')' || ch == '=' || ch == '^' ||
33 		ch == '[' || ch == ']' || ch == '<' || ch == '&' ||
34 		ch == '>' || ch == ',' || ch == '|' || ch == '~' ||
35 		ch == '$' || ch == ':' || ch == '%')
36 		return true;
37 	return false;
38 }
39 
ColouriseAPDLDoc(unsigned int startPos,int length,int initStyle,WordList * keywordlists[],Accessor & styler)40 static void ColouriseAPDLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
41                             Accessor &styler) {
42 
43 	int stringStart = ' ';
44 
45 	WordList &processors = *keywordlists[0];
46 	WordList &commands = *keywordlists[1];
47 	WordList &slashcommands = *keywordlists[2];
48 	WordList &starcommands = *keywordlists[3];
49 	WordList &arguments = *keywordlists[4];
50 	WordList &functions = *keywordlists[5];
51 
52 	// Do not leak onto next line
53 	initStyle = SCE_APDL_DEFAULT;
54 	StyleContext sc(startPos, length, initStyle, styler);
55 
56 	for (; sc.More(); sc.Forward()) {
57 		// Determine if the current state should terminate.
58 		if (sc.state == SCE_APDL_NUMBER) {
59 			if (!(IsADigit(sc.ch) || sc.ch == '.' || (sc.ch == 'e' || sc.ch == 'E') ||
60 				((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) {
61 				sc.SetState(SCE_APDL_DEFAULT);
62 			}
63 		} else if (sc.state == SCE_APDL_COMMENT) {
64 			if (sc.atLineEnd) {
65 				sc.SetState(SCE_APDL_DEFAULT);
66 			}
67 		} else if (sc.state == SCE_APDL_COMMENTBLOCK) {
68 			if (sc.atLineEnd) {
69 				if (sc.ch == '\r') {
70 				sc.Forward();
71 				}
72 				sc.ForwardSetState(SCE_APDL_DEFAULT);
73 			}
74 		} else if (sc.state == SCE_APDL_STRING) {
75 			if (sc.atLineEnd) {
76 				sc.SetState(SCE_APDL_DEFAULT);
77 			} else if ((sc.ch == '\'' && stringStart == '\'') || (sc.ch == '\"' && stringStart == '\"')) {
78 				sc.ForwardSetState(SCE_APDL_DEFAULT);
79 			}
80 		} else if (sc.state == SCE_APDL_WORD) {
81 			if (!IsAWordChar(sc.ch)) {
82 				char s[100];
83 				sc.GetCurrentLowered(s, sizeof(s));
84 				if (processors.InList(s)) {
85 					sc.ChangeState(SCE_APDL_PROCESSOR);
86 				} else if (slashcommands.InList(s)) {
87 					sc.ChangeState(SCE_APDL_SLASHCOMMAND);
88 				} else if (starcommands.InList(s)) {
89 					sc.ChangeState(SCE_APDL_STARCOMMAND);
90 				} else if (commands.InList(s)) {
91 					sc.ChangeState(SCE_APDL_COMMAND);
92 				} else if (arguments.InList(s)) {
93 					sc.ChangeState(SCE_APDL_ARGUMENT);
94 				} else if (functions.InList(s)) {
95 					sc.ChangeState(SCE_APDL_FUNCTION);
96 				}
97 				sc.SetState(SCE_APDL_DEFAULT);
98 			}
99 		} else if (sc.state == SCE_APDL_OPERATOR) {
100 			if (!IsAnOperator(static_cast<char>(sc.ch))) {
101 			    sc.SetState(SCE_APDL_DEFAULT);
102 			}
103 		}
104 
105 		// Determine if a new state should be entered.
106 		if (sc.state == SCE_APDL_DEFAULT) {
107 			if (sc.ch == '!' && sc.chNext == '!') {
108 				sc.SetState(SCE_APDL_COMMENTBLOCK);
109 			} else if (sc.ch == '!') {
110 				sc.SetState(SCE_APDL_COMMENT);
111 			} else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
112 				sc.SetState(SCE_APDL_NUMBER);
113 			} else if (sc.ch == '\'' || sc.ch == '\"') {
114 				sc.SetState(SCE_APDL_STRING);
115 				stringStart = sc.ch;
116 			} else if (IsAWordChar(sc.ch) || ((sc.ch == '*' || sc.ch == '/') && !isgraph(sc.chPrev))) {
117 				sc.SetState(SCE_APDL_WORD);
118 			} else if (IsAnOperator(static_cast<char>(sc.ch))) {
119 				sc.SetState(SCE_APDL_OPERATOR);
120 			}
121 		}
122 	}
123 	sc.Complete();
124 }
125 
126 static const char * const apdlWordListDesc[] = {
127     "processors",
128     "commands",
129     "slashommands",
130     "starcommands",
131     "arguments",
132     "functions",
133     0
134 };
135 
136 LexerModule lmAPDL(SCLEX_APDL, ColouriseAPDLDoc, "apdl", 0, apdlWordListDesc);
137