Repository navigation
Expand file tree
/
Copy pathtokenizer.js
More file actions
150 lines (134 loc) · 5.36 KB
/
Copy pathtokenizer.js
File metadata and controls
150 lines (134 loc) · 5.36 KB
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
/// Tokenises a string of source code by performing a regular expression, breaking it up into tokens of groups 'name', 'number', 'string' and 'punctuator'.
class Tokenizer
{
// Attributes
//-----------
///< A reference to the Google re2 regexp2 object that will perform the regular expression capture.
//_regularExpression = null;
// Constructor
//------------
/// Initialises the Tokenizer by:
/// - Creating and assigning an instance of a RegExp object.
constructor()
{
this._regularExpression = /(\u0020+|\u0009+)|(\/\/.*|\/\*|\*\/)|([_a-zA-Z][a-zA-Z_0-9]*)|(0x[0-9a-fA-F]+|\d+(?:\.\d+)?(?:[eE][+\-]?\d+)?)|(\"(?:[^\"\\]|\\(?:[nr\"\\]|x[0-9a-fA-F]{2}))*\"|'(?:[^'\\]|\\(?:[nr'\\]|u[0-9a-fA-F]{4}))*')|(\*=|[(){}\[\]?.,:;~*\/%]|<-|&&?|\|\|?|\^|<<|>>|>>>|==?|!=|\+\+|--|[+\-<>]=?>?|[!=](?:==)?|@)/;
}
// Methods
//--------
/// Parses (via a regular expression) a source code string, line by line, producing an array of raw (rudimentary) tokens,
/// categorised as either a 'name', 'number', 'string' or 'punctuator'.
/// \param source a string of compatible source code to be parsed and tokenized.
/// \return an array of raw (rudimentary) tokens.
parse( source )
{
let regularExpression = this._regularExpression;
let tokens = [];
var blockComment = false;
// Split the source up into one entry per line
let lines = source.split( "\n" );
// Parse each line, one at a time
lines.forEach( function (line, lineNumber)
{
var columnNumber = 0;
while( columnNumber < line.length )
{
let captives = regularExpression.exec( line.substr( columnNumber, line.length ) );
if( captives == null )
{
break;
throw "Syntax Error on line " + lineNumber + " column " + columnNumber;
}
if( captives[2] != null )
{
if( blockComment == false )
{
if( captives[2] == "/*" )
{
blockComment = true;
continue;
}
}
else
{
if( captives[2] == "*/" )
{
blockComment = false;
continue;
}
}
}
if( blockComment == false )
{
if( captives[3] != null )
{
// Name
tokens.push(
{
type : "name", value : captives[3],
lineNumber : lineNumber, columnNumber : columnNumber
});
}
else if( captives[4] != null )
{
// Number
let number = captives[4];
try
{
if( number.search( "." ) == 0 )
{
number = parseInt( number );
}
else
{
number = parseFloat( number );
}
}
catch( error )
{
throw "Type Error on line " + lineNumber + " column " + columnNumber;
}
tokens.push(
{
type : "number", value : number,
lineNumber : lineNumber, columnNumber : columnNumber
});
}
else if( captives[5] != null )
{
// String
tokens.push(
{
type : "string", value : captives[5],
lineNumber : lineNumber, columnNumber : columnNumber
});
}
else if( captives[6] != null )
{
// Punctuator
tokens.push(
{
type : "punctuator", value : captives[6],
lineNumber : lineNumber, columnNumber : columnNumber
});
}
}
var newColumnNumber = 0;
captives.forEach( function ( captive )
{
if( captive != null && captive.length > newColumnNumber ) { newColumnNumber = captive.length; }
});
columnNumber += newColumnNumber;
}
if( tokens.length > 0 && tokens[tokens.length-1].type != "newline" )
{
tokens.push(
{
type : "newline", value : "\n",
lineNumber : lineNumber, columnNumber : columnNumber
});
}
});
return tokens;
}
}
export { Tokenizer };