jlex 1.1.2 → 1.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,3 +1,6 @@
1
+
2
+ # jlex [![NPM Version](https://img.shields.io/npm/v/jlex)](https://www.npmjs.com/package/jlex)
3
+
1
4
  ## Install
2
5
 
3
6
  `npm i jlex`
@@ -14,30 +17,30 @@ npx jlex <package name>
14
17
  `jlex` is a tiny wrapper around `jison-lex` that allows you to use the script
15
18
  `jlex` as standalone (`flex` like) processor.
16
19
 
17
- Assuming the following lexer in file `example.js`:
20
+ Assuming the following lexer in file [examples/example.l](examples/example.l):
18
21
 
19
22
  ```
23
+ comment [/][*](.|[\r\n])*?[*][/]
20
24
  %%
21
- \s+ /* skip whitespace */
25
+ \s+|{comment} /* skip whitespace */
22
26
  [0-9]+ return 'NUMBER';
23
- "-" return '-';
27
+ [-+*/] return 'OPERATOR';
24
28
  <<EOF>> return 'EOF';
25
- . return 'INVALID';%
29
+ . return 'INVALID';
26
30
  ```
27
31
 
28
32
  Compile it with:
29
33
 
30
34
  ```
31
- ➜ jlex-test npx jlex example
32
- Processing file: example
33
- Writing file: example.js
35
+ npx jlex examples/example.l
34
36
  ```
35
37
 
36
- This produces a Common.JS module `example.js` you can use with a simple `require` like in the file `main.js` below:
38
+ This produces a Common.JS module `examples/example.js` you can use with a simple `require` like in the file [main.js](examples/main.js) below:
37
39
 
38
40
  ```js
39
41
  const lex = require("./example");
40
- lex.setInput("2\n-\n3")
42
+ const input = process.argv[2] || "2\n-/* a comment*/\n3";
43
+ lex.setInput(input);
41
44
 
42
45
  const results = [];
43
46
 
@@ -46,38 +49,13 @@ results.push({ type: lex.lex(), lexeme: lex.yytext, loc: lex.yylloc });
46
49
  results.push({ type: lex.lex(), lexeme: lex.yytext, loc: lex.yylloc });
47
50
  results.push({ type: lex.lex(), lexeme: lex.yytext, loc: lex.yylloc });
48
51
 
49
- console.log(results);
50
- /*
51
- ➜ examples git:(main) ✗ node main.js
52
- [
53
- {
54
- type: 'NUMBER',
55
- lexeme: '2',
56
- loc: { first_line: 1, last_line: 1, first_column: 0, last_column: 1 }
57
- },
58
- {
59
- type: '-',
60
- lexeme: '-',
61
- loc: { first_line: 2, last_line: 2, first_column: 0, last_column: 1 }
62
- },
63
- {
64
- type: 'NUMBER',
65
- lexeme: '3',
66
- loc: { first_line: 3, last_line: 3, first_column: 0, last_column: 1 }
67
- },
68
- {
69
- type: 'EOF',
70
- lexeme: '',
71
- loc: { first_line: 3, last_line: 3, first_column: 1, last_column: 1 }
72
- }
73
- ]
74
- */
52
+ console.log(results);
75
53
  ```
76
54
  When you execute the former program, you get:
77
55
 
78
56
 
79
57
  ```js
80
- ➜ jlex-test node main.js
58
+ ➜ jlex git:(main) ✗ node examples/main.js
81
59
  [
82
60
  {
83
61
  type: 'NUMBER',
@@ -85,7 +63,7 @@ When you execute the former program, you get:
85
63
  loc: { first_line: 1, last_line: 1, first_column: 0, last_column: 1 }
86
64
  },
87
65
  {
88
- type: '-',
66
+ type: 'OPERATOR',
89
67
  lexeme: '-',
90
68
  loc: { first_line: 2, last_line: 2, first_column: 0, last_column: 1 }
91
69
  },
@@ -104,7 +82,7 @@ When you execute the former program, you get:
104
82
 
105
83
  ## Using the lexer from a Jison grammar
106
84
 
107
- In file [examples/grammar.jison](examples/grammar.jison) you'll find an example
85
+ In file [examples/grammar.jison](examples/grammar.jison#L32-L33) you'll find an example
108
86
  of setting the generated lexer to be used from a Jison grammar. The key is
109
87
  to set the `lex` attribute of the `parser` object to the generated lexer:
110
88
 
@@ -121,7 +99,7 @@ Compile the grammar with:
121
99
 
122
100
  And use the parser:
123
101
 
124
- ```
102
+ ```js
125
103
  ➜ jlex git:(main) ✗ node
126
104
  Welcome to Node.js v25.6.0.
127
105
  Type ".help" for more information.
@@ -183,4 +161,73 @@ Here is a description of the attributes of the lexer object:
183
161
  rules: [ /^(?:\s+)/, /^(?:[0-9]+)/, /^(?:-)/, /^(?:$)/, /^(?:.)/ ],
184
162
  conditions: { INITIAL: { rules: [Array], inclusive: true } }
185
163
  }
164
+ ```
165
+
166
+ ## Writing a Jison compatible lexer by hand
167
+
168
+ See file [examples/manual-lexer.js](examples/manual-lexer.js) to see an example that
169
+ illustrates how to write a Jison compatible lexer by hand.
170
+
171
+ To use with the [grammar](examples/grammar.jison#L33-L34) in the `examples` folder, set the `parser.lexer` to the hand-written one:
172
+
173
+ ```diff
174
+ ➜ jlex git:(main) ✗ git -P diff examples/grammar.jison
175
+ diff --git a/examples/grammar.jison b/examples/grammar.jison
176
+ index 0b99d40..c9e974d 100644
177
+ --- a/examples/grammar.jison
178
+ +++ b/examples/grammar.jison
179
+ @@ -12,6 +12,7 @@ expr
180
+ {
181
+ $$ = {
182
+ type: "OPERATOR",
183
+ + lexeme: $2,
184
+ left: $1,
185
+ right: $3,
186
+ loc: @2
187
+ @@ -29,5 +30,7 @@ expr
188
+
189
+ %%
190
+
191
+ -const lexer = require("./example.js");
192
+ +//const lexer = require("./example.js");
193
+ +const lexer = require("./manual-lexer.js");
194
+ +
195
+ parser.lexer = lexer;
196
+
197
+ ```
198
+
199
+ Then compile the grammar:
200
+
201
+ ```
202
+ ➜ jlex git:(main) ✗ npx jison examples/grammar.jison -o examples/parser.js
203
+ ```
204
+ and use it like this:
205
+
206
+ ```js
207
+ ➜ jlex git:(main) ✗ node
208
+ Welcome to Node.js v25.6.0.
209
+ Type ".help" for more information.
210
+ > p = require("./examples/parser.js")
211
+ {
212
+ parser: { yy: {} },
213
+ Parser: [Function: Parser],
214
+ parse: [Function (anonymous)],
215
+ main: [Function: commonjsMain]
216
+ }
217
+ > p.parse("2*3")
218
+ {
219
+ type: 'OPERATOR',
220
+ lexeme: '*',
221
+ left: {
222
+ type: 'number',
223
+ value: 2,
224
+ loc: { first_line: 1, last_line: 1, first_column: 0, last_column: 1 }
225
+ },
226
+ right: {
227
+ type: 'number',
228
+ value: 3,
229
+ loc: { first_line: 1, last_line: 1, first_column: 2, last_column: 3 }
230
+ },
231
+ loc: { first_line: 1, last_line: 1, first_column: 1, last_column: 2 }
232
+ }
186
233
  ```
@@ -12,6 +12,7 @@ expr
12
12
  {
13
13
  $$ = {
14
14
  type: "OPERATOR",
15
+ lexeme: $2,
15
16
  left: $1,
16
17
  right: $3,
17
18
  loc: @2
@@ -30,4 +31,6 @@ expr
30
31
  %%
31
32
 
32
33
  const lexer = require("./example.js");
34
+ //const lexer = require("./manual-lexer.js");
35
+
33
36
  parser.lexer = lexer;
@@ -0,0 +1,87 @@
1
+ const lexer = {
2
+ input: "",
3
+ index: 0,
4
+
5
+ yytext: "",
6
+ yylineno: 0, // base 0 internamente
7
+ yylloc: {},
8
+
9
+ setInput(input) {
10
+ this.input = input;
11
+ this.index = 0;
12
+ this.yylineno = 0;
13
+ this.column = 0;
14
+ return this;
15
+ },
16
+
17
+ lex() {
18
+ if (this.index >= this.input.length) {
19
+ return 'EOF' /* this.EOF */;
20
+ }
21
+
22
+ // Saltar espacios
23
+ while (/\s+/.test(this.input[this.index])) {
24
+ this.advance(this.input[this.index]);
25
+ }
26
+
27
+ if (this.index >= this.input.length) {
28
+ return this.EOF;
29
+ }
30
+
31
+ const startLine = this.yylineno + 1; // Jison usa base 1
32
+ const startColumn = this.column;
33
+
34
+ const char = this.input[this.index];
35
+
36
+ // OPERATOR
37
+ if (/[-+*\/]/.test(char)) {
38
+ this.yytext = char;
39
+ this.advance(char);
40
+
41
+ this.yylloc = {
42
+ first_line: startLine,
43
+ last_line: this.yylineno + 1,
44
+ first_column: startColumn,
45
+ last_column: this.column
46
+ };
47
+
48
+ return "OPERATOR";
49
+ }
50
+
51
+ // NUMBER (soporta múltiples dígitos)
52
+ if (/\d/.test(char)) {
53
+ let num = "";
54
+
55
+ while (/\d/.test(this.input[this.index])) {
56
+ num += this.input[this.index];
57
+ this.advance(this.input[this.index]);
58
+ }
59
+
60
+ this.yytext = num;
61
+
62
+ this.yylloc = {
63
+ first_line: startLine,
64
+ last_line: this.yylineno + 1,
65
+ first_column: startColumn,
66
+ last_column: this.column
67
+ };
68
+
69
+ return "NUMBER";
70
+ }
71
+
72
+ throw new Error("Carácter inesperado: " + char);
73
+ },
74
+
75
+ advance(char) {
76
+ this.index++;
77
+
78
+ if (char === "\n") {
79
+ this.yylineno++;
80
+ this.column = 0;
81
+ } else {
82
+ this.column++;
83
+ }
84
+ }
85
+ };
86
+
87
+ module.exports = lexer;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jlex",
3
- "version": "1.1.2",
3
+ "version": "1.1.4",
4
4
  "description": "A wrapper around jison-lex to make it work as a standalone program like Flex",
5
5
  "keywords": [
6
6
  "jison-lex",