]>
Commit | Line | Data |
---|---|---|
a33203cb RD |
1 | // Scintilla source code edit control |
2 | /** @file LexAsn1.cxx | |
3 | ** Lexer for ASN.1 | |
4 | **/ | |
5 | // Copyright 2004 by Herr Pfarrer rpfarrer <at> yahoo <dot> de | |
6 | // Last Updated: 20/07/2004 | |
7 | // The License.txt file describes the conditions under which this software may be distributed. | |
1dcf666d | 8 | |
a33203cb RD |
9 | #include <stdlib.h> |
10 | #include <string.h> | |
a33203cb RD |
11 | #include <stdio.h> |
12 | #include <stdarg.h> | |
1dcf666d | 13 | #include <assert.h> |
a33203cb | 14 | |
1dcf666d RD |
15 | #include "ILexer.h" |
16 | #include "Scintilla.h" | |
17 | #include "SciLexer.h" | |
a33203cb | 18 | |
1dcf666d RD |
19 | #include "WordList.h" |
20 | #include "LexAccessor.h" | |
a33203cb RD |
21 | #include "Accessor.h" |
22 | #include "StyleContext.h" | |
1dcf666d RD |
23 | #include "CharacterSet.h" |
24 | #include "LexerModule.h" | |
a33203cb | 25 | |
7e0c58e9 RD |
26 | #ifdef SCI_NAMESPACE |
27 | using namespace Scintilla; | |
28 | #endif | |
29 | ||
a33203cb RD |
30 | // Some char test functions |
31 | static bool isAsn1Number(int ch) | |
32 | { | |
33 | return (ch >= '0' && ch <= '9'); | |
34 | } | |
35 | ||
36 | static bool isAsn1Letter(int ch) | |
37 | { | |
38 | return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); | |
39 | } | |
40 | ||
41 | static bool isAsn1Char(int ch) | |
42 | { | |
43 | return (ch == '-' ) || isAsn1Number(ch) || isAsn1Letter (ch); | |
44 | } | |
45 | ||
46 | // | |
47 | // Function determining the color of a given code portion | |
48 | // Based on a "state" | |
49 | // | |
50 | static void ColouriseAsn1Doc(unsigned int startPos, int length, int initStyle, WordList *keywordLists[], Accessor &styler) | |
51 | { | |
52 | // The keywords | |
53 | WordList &Keywords = *keywordLists[0]; | |
54 | WordList &Attributes = *keywordLists[1]; | |
55 | WordList &Descriptors = *keywordLists[2]; | |
56 | WordList &Types = *keywordLists[3]; | |
57 | ||
58 | // Parse the whole buffer character by character using StyleContext | |
59 | StyleContext sc(startPos, length, initStyle, styler); | |
60 | for (; sc.More(); sc.Forward()) | |
61 | { | |
62 | // The state engine | |
63 | switch (sc.state) | |
64 | { | |
65 | case SCE_ASN1_DEFAULT: // Plain characters | |
66 | asn1_default: | |
67 | if (sc.ch == '-' && sc.chNext == '-') | |
68 | // A comment begins here | |
69 | sc.SetState(SCE_ASN1_COMMENT); | |
70 | else if (sc.ch == '"') | |
71 | // A string begins here | |
72 | sc.SetState(SCE_ASN1_STRING); | |
73 | else if (isAsn1Number (sc.ch)) | |
74 | // A number starts here (identifier should start with a letter in ASN.1) | |
75 | sc.SetState(SCE_ASN1_SCALAR); | |
76 | else if (isAsn1Char (sc.ch)) | |
77 | // An identifier starts here (identifier always start with a letter) | |
78 | sc.SetState(SCE_ASN1_IDENTIFIER); | |
79 | else if (sc.ch == ':') | |
80 | // A ::= operator starts here | |
81 | sc.SetState(SCE_ASN1_OPERATOR); | |
82 | break; | |
83 | case SCE_ASN1_COMMENT: // A comment | |
84 | if (sc.ch == '\r' || sc.ch == '\n') | |
85 | // A comment ends here | |
86 | sc.SetState(SCE_ASN1_DEFAULT); | |
87 | break; | |
88 | case SCE_ASN1_IDENTIFIER: // An identifier (keyword, attribute, descriptor or type) | |
89 | if (!isAsn1Char (sc.ch)) | |
90 | { | |
91 | // The end of identifier is here: we can look for it in lists by now and change its state | |
92 | char s[100]; | |
93 | sc.GetCurrent(s, sizeof(s)); | |
94 | if (Keywords.InList(s)) | |
95 | // It's a keyword, change its state | |
96 | sc.ChangeState(SCE_ASN1_KEYWORD); | |
97 | else if (Attributes.InList(s)) | |
98 | // It's an attribute, change its state | |
99 | sc.ChangeState(SCE_ASN1_ATTRIBUTE); | |
100 | else if (Descriptors.InList(s)) | |
101 | // It's a descriptor, change its state | |
102 | sc.ChangeState(SCE_ASN1_DESCRIPTOR); | |
103 | else if (Types.InList(s)) | |
104 | // It's a type, change its state | |
105 | sc.ChangeState(SCE_ASN1_TYPE); | |
106 | ||
107 | // Set to default now | |
108 | sc.SetState(SCE_ASN1_DEFAULT); | |
109 | } | |
110 | break; | |
111 | case SCE_ASN1_STRING: // A string delimited by "" | |
112 | if (sc.ch == '"') | |
113 | { | |
114 | // A string ends here | |
115 | sc.ForwardSetState(SCE_ASN1_DEFAULT); | |
116 | ||
117 | // To correctly manage a char sticking to the string quote | |
118 | goto asn1_default; | |
119 | } | |
120 | break; | |
121 | case SCE_ASN1_SCALAR: // A plain number | |
122 | if (!isAsn1Number (sc.ch)) | |
123 | // A number ends here | |
124 | sc.SetState(SCE_ASN1_DEFAULT); | |
125 | break; | |
126 | case SCE_ASN1_OPERATOR: // The affectation operator ::= and wath follows (eg: ::= { org 6 } OID or ::= 12 trap) | |
127 | if (sc.ch == '{') | |
128 | { | |
129 | // An OID definition starts here: enter the sub loop | |
130 | for (; sc.More(); sc.Forward()) | |
131 | { | |
132 | if (isAsn1Number (sc.ch) && (!isAsn1Char (sc.chPrev) || isAsn1Number (sc.chPrev))) | |
133 | // The OID number is highlighted | |
134 | sc.SetState(SCE_ASN1_OID); | |
135 | else if (isAsn1Char (sc.ch)) | |
136 | // The OID parent identifier is plain | |
137 | sc.SetState(SCE_ASN1_IDENTIFIER); | |
138 | else | |
139 | sc.SetState(SCE_ASN1_DEFAULT); | |
140 | ||
141 | if (sc.ch == '}') | |
142 | // Here ends the OID and the operator sub loop: go back to main loop | |
143 | break; | |
144 | } | |
145 | } | |
146 | else if (isAsn1Number (sc.ch)) | |
147 | { | |
148 | // A trap number definition starts here: enter the sub loop | |
149 | for (; sc.More(); sc.Forward()) | |
150 | { | |
151 | if (isAsn1Number (sc.ch)) | |
152 | // The trap number is highlighted | |
153 | sc.SetState(SCE_ASN1_OID); | |
154 | else | |
155 | { | |
156 | // The number ends here: go back to main loop | |
157 | sc.SetState(SCE_ASN1_DEFAULT); | |
158 | break; | |
159 | } | |
160 | } | |
161 | } | |
162 | else if (sc.ch != ':' && sc.ch != '=' && sc.ch != ' ') | |
163 | // The operator doesn't imply an OID definition nor a trap, back to main loop | |
164 | goto asn1_default; // To be sure to handle actually the state change | |
165 | break; | |
166 | } | |
167 | } | |
168 | sc.Complete(); | |
169 | } | |
170 | ||
171 | static void FoldAsn1Doc(unsigned int, int, int, WordList *[], Accessor &styler) | |
172 | { | |
173 | // No folding enabled, no reason to continue... | |
174 | if( styler.GetPropertyInt("fold") == 0 ) | |
175 | return; | |
176 | ||
177 | // No folding implemented: doesn't make sense for ASN.1 | |
178 | } | |
179 | ||
180 | static const char * const asn1WordLists[] = { | |
181 | "Keywords", | |
182 | "Attributes", | |
183 | "Descriptors", | |
184 | "Types", | |
185 | 0, }; | |
186 | ||
187 | ||
1e9bafca | 188 | LexerModule lmAns1(SCLEX_ASN1, ColouriseAsn1Doc, "asn1", FoldAsn1Doc, asn1WordLists); |