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