File: JSLexer.l

package info (click to toggle)
codelite 12.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 95,112 kB
  • sloc: cpp: 424,040; ansic: 18,284; php: 9,569; lex: 4,186; yacc: 2,820; python: 2,294; sh: 312; makefile: 51; xml: 13
file content (318 lines) | stat: -rw-r--r-- 9,564 bytes parent folder | download | duplicates (3)
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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
%{
//
//====================--------------------------------------------------------------
// Eran Ifrah 2014 (c)
//====================--------------------------------------------------------------
//
// To generate a source file from this .l file, you will need
// a flex version 2.5.34 and later
// Under Windows, you will need to run the following command 
// from within *MSYS* terminal (or run codelite from an MSYS shell):
// /usr/bin/flex -Pjs --batch --outfile=JSLexer.cpp JSLexer.l
//
//====================--------------------------------------------------------------
//
extern "C" int yywrap(void*) { return 1; }

#include <wx/string.h>
#include <string>
#include <wx/filename.h>
#include "JSLexerAPI.h"
#include "JSLexerTokens.h"

#define YY_FATAL_ERROR(x)
#define YYSTYPE char*
#define ECHO
#define P(s) fprintf(stderr, "%s\n", s)

#define YY_NO_UNISTD_H
#define YY_USER_ACTION  yycolumn += yyleng;

#define RETURN_WHITESPACE() 
#define RETURN_NEWLINE() 

%}

/* regex and modes */

/* options */
%option yylineno
%option default
%option reentrant

%x WRAP_PREP
%x CPP_COMMENT
%x C_COMMENT

identifier [$a-zA-Z_][$0-9a-zA-Z_]*
exponent_part [eE][-+]?[0-9]+
fractional_constant ([0-9]*"."[0-9]+)|([0-9]+".")
floating_constant (({fractional_constant}{exponent_part}?)|([0-9]+{exponent_part}))[FfLl]?

integer_suffix_opt ([uU]?[lL]?)|([lL][uU])
decimal_constant [1-9][0-9]*{integer_suffix_opt}
octal_constant "0"[0-7]*{integer_suffix_opt}
hex_constant "0"[xX][0-9a-fA-F]+{integer_suffix_opt}

simple_escape [abfnrtv'"?\\]
octal_escape  [0-7]{1,3}
hex_escape "x"[0-9a-fA-F]+

escape_sequence [\\]({simple_escape}|{octal_escape}|{hex_escape})
c_char [^'\\\n]|{escape_sequence}
s_char [^"\\\n]|{escape_sequence}

h_tab [\011]
form_feed [\014]
v_tab [\013]
c_return [\015]

horizontal_white [ ]|{h_tab}

%% 
<<EOF>> {yyterminate();}
<INITIAL>function {return kJS_FUNCTION;}
<INITIAL>prototype {return kJS_PROTOTYPE;}
<INITIAL>var {return kJS_VAR;}
<INITIAL>this {return kJS_THIS;}
<INITIAL>catch {return kJS_CATCH;}
<INITIAL>throw {return kJS_THROW;}
<INITIAL>switch {return kJS_SWITCH;}
<INITIAL>case {return kJS_CASE;}
<INITIAL>for {return kJS_FOR;}
<INITIAL>return {return kJS_RETURN;}
<INITIAL>new {return kJS_NEW;}
<INITIAL>delete {return kJS_DELETE;}
<INITIAL>"." {return kJS_DOT;}
<INITIAL>true {return kJS_TRUE;}
<INITIAL>false {return kJS_FALSE;}
<INITIAL>null {return kJS_NULL;}
<INITIAL>typeof {return kJS_TYPEOF;}
<INITIAL>void {return kJS_VOID;}
<INITIAL>instanceof {return kJS_INSTANCEOF;}
<INITIAL>{horizontal_white}+ { RETURN_WHITESPACE(); }
<INITIAL>({v_tab}|{c_return}|{form_feed})+ {RETURN_WHITESPACE();}
<INITIAL>({horizontal_white}|{v_tab}|{c_return}|{form_feed})*"\n" { RETURN_NEWLINE(); }
<INITIAL>{decimal_constant}  { return kJS_DEC_NUMBER;}
<INITIAL>{octal_constant}    { return kJS_OCTAL_NUMBER;}
<INITIAL>{hex_constant}      { return kJS_HEX_NUMBER; }
<INITIAL>{floating_constant} { return kJS_FLOAT_NUMBER;}
<INITIAL>"++"                { return kJS_PLUS_PLUS; }
<INITIAL>"--"                { return kJS_MINUS_MINUS; }
<INITIAL>"<<"                { return kJS_LS; }
<INITIAL>">>"                { return kJS_RS; }
<INITIAL>"<="                { return kJS_LE; }
<INITIAL>">="                { return kJS_GE; }
<INITIAL>"=="                { return kJS_EQUAL; }
<INITIAL>"==="               { return kJS_EQUAL3; }
<INITIAL>"!="                { return kJS_NOT_EQUAL; }
<INITIAL>"&&"                { return kJS_AND_AND;}
<INITIAL>"||"                { return kJS_OR_OR;}
<INITIAL>"*="                { return kJS_STAR_EQUAL;}
<INITIAL>"/="                { return kJS_SLASH_EQUAL;}
<INITIAL>"%="                { return kJS_DIV_EQUAL;}
<INITIAL>"+="                { return kJS_PLUS_EQUAL;}
<INITIAL>"-="                { return kJS_MINUS_EQUAL;}
<INITIAL>"<<="               { return kJS_LS_ASSIGN;}
<INITIAL>">>="               { return kJS_RS_ASSIGN;}
<INITIAL>"&="                { return kJS_AND_EQUAL;}
<INITIAL>"^="                { return kJS_POW_EQUAL;}
<INITIAL>"|="                { return kJS_OR_EQUAL;}
<INITIAL>"L"?[']{c_char}*['] {
    return kJS_STRING;
}
<INITIAL>"L"?["]{s_char}*["] {
    return kJS_STRING;
}
<INITIAL>"/*" {
    // Clear the comment collected
    BEGIN C_COMMENT;
    
    JSLexerUserData* userData = (JSLexerUserData*)yyg->yyextra_r;
    if(userData->IsCollectingComments()) {
        userData->ClearComment();
        userData->AppendToComment("/*");
        userData->SetCommentStartLine(yylineno);
    }
}
<C_COMMENT>"*/" {
    JSLexerUserData* userData = (JSLexerUserData*)yyg->yyextra_r;
    if(userData->IsCollectingComments()) {
        userData->AppendToComment("*/");
        userData->SetCommentEndLine(yylineno);
    }
    BEGIN INITIAL;
    if(userData->IsCollectingComments()) {
        return kJS_C_COMMENT;
    }
}
<C_COMMENT>"\n" { 
    JSLexerUserData* userData = (JSLexerUserData*)yyg->yyextra_r;
    if(userData->IsCollectingComments()) {
        userData->AppendToComment("\n");
    }
}
<C_COMMENT>. {
    JSLexerUserData* userData = (JSLexerUserData*)yyg->yyextra_r;
    if(userData->IsCollectingComments()) {
        std::string stdstr = std::string(1, yytext[0]);
        userData->AppendToComment(wxString(stdstr.c_str(), wxConvUTF8));
    }
}

<INITIAL>"//" {
    BEGIN CPP_COMMENT;
    JSLexerUserData* userData = (JSLexerUserData*)yyg->yyextra_r;
    if(userData->IsCollectingComments()) {
        userData->ClearComment();
        userData->AppendToComment("//");
        userData->SetCommentStartLine(yylineno);
    }
}

<CPP_COMMENT>"\\\n" { 
}
<CPP_COMMENT>"\\\r\n" { 
}
<CPP_COMMENT>"\n" {
    BEGIN INITIAL;
    JSLexerUserData* userData = (JSLexerUserData*)yyg->yyextra_r;
    if(userData->IsCollectingComments()) {
        userData->AppendToComment("\n");
        return kJS_CXX_COMMENT;
    }
}
<CPP_COMMENT>. { 
    JSLexerUserData* userData = (JSLexerUserData*)yyg->yyextra_r;
    if(userData->IsCollectingComments()) {
        std::string stdstr = std::string(1, yytext[0]);
        userData->AppendToComment(wxString(stdstr.c_str(), wxConvUTF8));
    }
}
<INITIAL>{identifier} { 
    return kJS_IDENTIFIER;
}
<INITIAL>. { 
    return yytext[0];
}

%%

//=============-------------------------------
// API methods implementation
//=============-------------------------------

void* jsLexerNew(const wxString& content, size_t options )
{
    yyscan_t scanner;
    yylex_init(&scanner);
    struct yyguts_t * yyg = (struct yyguts_t*)scanner;
    JSLexerUserData *userData = new JSLexerUserData(options);
    
    // keep the file pointer (and make sure we close it at the end)
    userData->SetCurrentPF(NULL);
    yyg->yyextra_r = userData;
    
    wxCharBuffer cb = content.mb_str(wxConvUTF8);
    yy_switch_to_buffer(yy_scan_string(cb.data(), scanner), scanner);
    yycolumn = 1;
    yylineno = 0;
    return scanner;
}

void* jsLexerNew(const wxFileName& filename, size_t options )
{
    wxFileName fn = filename;
    if(fn.IsRelative()) {
        fn.MakeAbsolute();
    }
    
    FILE* fp = ::fopen(fn.GetFullPath().mb_str(wxConvUTF8).data(), "rb");
    if(!fp) {
        return NULL;
    }
    yyscan_t scanner;
    yylex_init(&scanner);
    struct yyguts_t * yyg = (struct yyguts_t*)scanner;
    JSLexerUserData *userData = new JSLexerUserData(options);
    
    // keep the file pointer (and make sure we close it at the end)
    userData->SetCurrentPF(fp);
    yyg->yyextra_r = userData;
    
    yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE, scanner), scanner);
    yycolumn = 1;
    yylineno = 0;
    return scanner;
}

void jsLexerDestroy(void** scanner)
{
    struct yyguts_t * yyg = (struct yyguts_t*)(*scanner);
    delete (JSLexerUserData*)yyg->yyextra_r;
    yy_delete_buffer(YY_CURRENT_BUFFER, *scanner);

    yylex_destroy(*scanner);
    *scanner = NULL;
}

void jsLexerUnget(void* scanner)
{
    // return the entire token back to the input stream
    struct yyguts_t * yyg = (struct yyguts_t*)scanner;
    yyless(0);
}

wxString jsLexerText(void* scanner)
{
    struct yyguts_t * yyg = (struct yyguts_t*)scanner;
    return wxString(yytext, wxConvUTF8);
}

bool jsLexerNext(void* scanner, JSLexerToken& token)
{
    token.column = 0;
    token.type = yylex(scanner);
    if(token.type != 0) {
        struct yyguts_t * yyg = (struct yyguts_t*)scanner;
        JSLexerUserData* userData = (JSLexerUserData*)yyg->yyextra_r;
        switch(token.type) {
        case kJS_CXX_COMMENT:
            // One line up for CXX comments
            token.lineNumber = userData->GetCommentStartLine();
            token.comment = userData->GetComment();
            userData->ClearComment();
            break;
        case kJS_C_COMMENT:
            token.comment = userData->GetComment();
            userData->ClearComment();
            // for block comments, we want the last line of the comment
            // because we usually want to match it to the statement under it
            token.lineNumber = yylineno;
            break;
        default:
            token.lineNumber = yylineno;
            token.text = wxString(yytext, wxConvUTF8);
            token.column = yycolumn;
            break;
        }

    } else {
        token.text.Clear();
        token.lineNumber = 0;
        token.column = 0;
    }
    return token.type != 0;
}

wxString jsLexerCurrentToken(void* scanner)
{
    struct yyguts_t * yyg = (struct yyguts_t*)scanner;
    return yytext;
}

JSLexerUserData* jsLexerGetUserData(void* scanner)
{
    struct yyguts_t * yyg = (struct yyguts_t*)scanner;
    return (JSLexerUserData*) yyg->yyextra_r;
}