demotape 0.0.3 → 0.0.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.
- checksums.yaml +4 -4
- data/.github/workflows/ruby-tests.yml +1 -1
- data/.gitignore +8 -0
- data/CHANGELOG.md +6 -0
- data/CONTRIBUTING.md +2 -2
- data/README.md +19 -10
- data/editors/sublime-text/DemoTape.sublime-syntax +1 -1
- data/editors/vim/ftdetect/demotape.vim +1 -1
- data/editors/vim/syntax/demotape.vim +1 -1
- data/editors/vscode/LICENSE.md +20 -0
- data/editors/vscode/README.md +12 -2
- data/editors/vscode/RELEASE_PROCESS.md +10 -0
- data/editors/vscode/demotape.tmLanguage.json +7 -6
- data/editors/vscode/icon.png +0 -0
- data/editors/vscode/package.json +20 -4
- data/editors/zed/extension.toml +12 -0
- data/editors/zed/grammars/demotape.wasm +0 -0
- data/editors/zed/languages/demotape/config.toml +11 -0
- data/editors/zed/languages/demotape/highlights.scm +70 -0
- data/editors/zed/package-lock.json +6 -0
- data/editors/zed/tree-sitter/Cargo.toml +26 -0
- data/editors/zed/tree-sitter/binding.gyp +19 -0
- data/editors/zed/tree-sitter/bindings/node/binding.cc +28 -0
- data/editors/zed/tree-sitter/bindings/node/index.js +19 -0
- data/editors/zed/tree-sitter/bindings/rust/build.rs +40 -0
- data/editors/zed/tree-sitter/bindings/rust/lib.rs +52 -0
- data/editors/zed/tree-sitter/grammar.js +227 -0
- data/editors/zed/tree-sitter/package-lock.json +36 -0
- data/editors/zed/tree-sitter/package.json +27 -0
- data/editors/zed/tree-sitter/queries/highlights.scm +70 -0
- data/editors/zed/tree-sitter/src/grammar.json +1123 -0
- data/editors/zed/tree-sitter/src/node-types.json +862 -0
- data/editors/zed/tree-sitter/src/parser.c +9337 -0
- data/editors/zed/tree-sitter/src/tree_sitter/parser.h +224 -0
- data/exe/demotape +1 -0
- data/lib/demo_tape/cli.rb +10 -2
- data/lib/demo_tape/command.rb +1 -1
- data/lib/demo_tape/ext/thor.rb +17 -0
- data/lib/demo_tape/version.rb +1 -1
- metadata +28 -7
- data/demotape_new.y.backup +0 -160
- data/demotape_simple_test.y +0 -32
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
#ifndef TREE_SITTER_PARSER_H_
|
|
2
|
+
#define TREE_SITTER_PARSER_H_
|
|
3
|
+
|
|
4
|
+
#ifdef __cplusplus
|
|
5
|
+
extern "C" {
|
|
6
|
+
#endif
|
|
7
|
+
|
|
8
|
+
#include <stdbool.h>
|
|
9
|
+
#include <stdint.h>
|
|
10
|
+
#include <stdlib.h>
|
|
11
|
+
|
|
12
|
+
#define ts_builtin_sym_error ((TSSymbol)-1)
|
|
13
|
+
#define ts_builtin_sym_end 0
|
|
14
|
+
#define TREE_SITTER_SERIALIZATION_BUFFER_SIZE 1024
|
|
15
|
+
|
|
16
|
+
typedef uint16_t TSStateId;
|
|
17
|
+
|
|
18
|
+
#ifndef TREE_SITTER_API_H_
|
|
19
|
+
typedef uint16_t TSSymbol;
|
|
20
|
+
typedef uint16_t TSFieldId;
|
|
21
|
+
typedef struct TSLanguage TSLanguage;
|
|
22
|
+
#endif
|
|
23
|
+
|
|
24
|
+
typedef struct {
|
|
25
|
+
TSFieldId field_id;
|
|
26
|
+
uint8_t child_index;
|
|
27
|
+
bool inherited;
|
|
28
|
+
} TSFieldMapEntry;
|
|
29
|
+
|
|
30
|
+
typedef struct {
|
|
31
|
+
uint16_t index;
|
|
32
|
+
uint16_t length;
|
|
33
|
+
} TSFieldMapSlice;
|
|
34
|
+
|
|
35
|
+
typedef struct {
|
|
36
|
+
bool visible;
|
|
37
|
+
bool named;
|
|
38
|
+
bool supertype;
|
|
39
|
+
} TSSymbolMetadata;
|
|
40
|
+
|
|
41
|
+
typedef struct TSLexer TSLexer;
|
|
42
|
+
|
|
43
|
+
struct TSLexer {
|
|
44
|
+
int32_t lookahead;
|
|
45
|
+
TSSymbol result_symbol;
|
|
46
|
+
void (*advance)(TSLexer *, bool);
|
|
47
|
+
void (*mark_end)(TSLexer *);
|
|
48
|
+
uint32_t (*get_column)(TSLexer *);
|
|
49
|
+
bool (*is_at_included_range_start)(const TSLexer *);
|
|
50
|
+
bool (*eof)(const TSLexer *);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
typedef enum {
|
|
54
|
+
TSParseActionTypeShift,
|
|
55
|
+
TSParseActionTypeReduce,
|
|
56
|
+
TSParseActionTypeAccept,
|
|
57
|
+
TSParseActionTypeRecover,
|
|
58
|
+
} TSParseActionType;
|
|
59
|
+
|
|
60
|
+
typedef union {
|
|
61
|
+
struct {
|
|
62
|
+
uint8_t type;
|
|
63
|
+
TSStateId state;
|
|
64
|
+
bool extra;
|
|
65
|
+
bool repetition;
|
|
66
|
+
} shift;
|
|
67
|
+
struct {
|
|
68
|
+
uint8_t type;
|
|
69
|
+
uint8_t child_count;
|
|
70
|
+
TSSymbol symbol;
|
|
71
|
+
int16_t dynamic_precedence;
|
|
72
|
+
uint16_t production_id;
|
|
73
|
+
} reduce;
|
|
74
|
+
uint8_t type;
|
|
75
|
+
} TSParseAction;
|
|
76
|
+
|
|
77
|
+
typedef struct {
|
|
78
|
+
uint16_t lex_state;
|
|
79
|
+
uint16_t external_lex_state;
|
|
80
|
+
} TSLexMode;
|
|
81
|
+
|
|
82
|
+
typedef union {
|
|
83
|
+
TSParseAction action;
|
|
84
|
+
struct {
|
|
85
|
+
uint8_t count;
|
|
86
|
+
bool reusable;
|
|
87
|
+
} entry;
|
|
88
|
+
} TSParseActionEntry;
|
|
89
|
+
|
|
90
|
+
struct TSLanguage {
|
|
91
|
+
uint32_t version;
|
|
92
|
+
uint32_t symbol_count;
|
|
93
|
+
uint32_t alias_count;
|
|
94
|
+
uint32_t token_count;
|
|
95
|
+
uint32_t external_token_count;
|
|
96
|
+
uint32_t state_count;
|
|
97
|
+
uint32_t large_state_count;
|
|
98
|
+
uint32_t production_id_count;
|
|
99
|
+
uint32_t field_count;
|
|
100
|
+
uint16_t max_alias_sequence_length;
|
|
101
|
+
const uint16_t *parse_table;
|
|
102
|
+
const uint16_t *small_parse_table;
|
|
103
|
+
const uint32_t *small_parse_table_map;
|
|
104
|
+
const TSParseActionEntry *parse_actions;
|
|
105
|
+
const char * const *symbol_names;
|
|
106
|
+
const char * const *field_names;
|
|
107
|
+
const TSFieldMapSlice *field_map_slices;
|
|
108
|
+
const TSFieldMapEntry *field_map_entries;
|
|
109
|
+
const TSSymbolMetadata *symbol_metadata;
|
|
110
|
+
const TSSymbol *public_symbol_map;
|
|
111
|
+
const uint16_t *alias_map;
|
|
112
|
+
const TSSymbol *alias_sequences;
|
|
113
|
+
const TSLexMode *lex_modes;
|
|
114
|
+
bool (*lex_fn)(TSLexer *, TSStateId);
|
|
115
|
+
bool (*keyword_lex_fn)(TSLexer *, TSStateId);
|
|
116
|
+
TSSymbol keyword_capture_token;
|
|
117
|
+
struct {
|
|
118
|
+
const bool *states;
|
|
119
|
+
const TSSymbol *symbol_map;
|
|
120
|
+
void *(*create)(void);
|
|
121
|
+
void (*destroy)(void *);
|
|
122
|
+
bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist);
|
|
123
|
+
unsigned (*serialize)(void *, char *);
|
|
124
|
+
void (*deserialize)(void *, const char *, unsigned);
|
|
125
|
+
} external_scanner;
|
|
126
|
+
const TSStateId *primary_state_ids;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
/*
|
|
130
|
+
* Lexer Macros
|
|
131
|
+
*/
|
|
132
|
+
|
|
133
|
+
#define START_LEXER() \
|
|
134
|
+
bool result = false; \
|
|
135
|
+
bool skip = false; \
|
|
136
|
+
bool eof = false; \
|
|
137
|
+
int32_t lookahead; \
|
|
138
|
+
goto start; \
|
|
139
|
+
next_state: \
|
|
140
|
+
lexer->advance(lexer, skip); \
|
|
141
|
+
start: \
|
|
142
|
+
skip = false; \
|
|
143
|
+
lookahead = lexer->lookahead;
|
|
144
|
+
|
|
145
|
+
#define ADVANCE(state_value) \
|
|
146
|
+
{ \
|
|
147
|
+
state = state_value; \
|
|
148
|
+
goto next_state; \
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
#define SKIP(state_value) \
|
|
152
|
+
{ \
|
|
153
|
+
skip = true; \
|
|
154
|
+
state = state_value; \
|
|
155
|
+
goto next_state; \
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
#define ACCEPT_TOKEN(symbol_value) \
|
|
159
|
+
result = true; \
|
|
160
|
+
lexer->result_symbol = symbol_value; \
|
|
161
|
+
lexer->mark_end(lexer);
|
|
162
|
+
|
|
163
|
+
#define END_STATE() return result;
|
|
164
|
+
|
|
165
|
+
/*
|
|
166
|
+
* Parse Table Macros
|
|
167
|
+
*/
|
|
168
|
+
|
|
169
|
+
#define SMALL_STATE(id) id - LARGE_STATE_COUNT
|
|
170
|
+
|
|
171
|
+
#define STATE(id) id
|
|
172
|
+
|
|
173
|
+
#define ACTIONS(id) id
|
|
174
|
+
|
|
175
|
+
#define SHIFT(state_value) \
|
|
176
|
+
{{ \
|
|
177
|
+
.shift = { \
|
|
178
|
+
.type = TSParseActionTypeShift, \
|
|
179
|
+
.state = state_value \
|
|
180
|
+
} \
|
|
181
|
+
}}
|
|
182
|
+
|
|
183
|
+
#define SHIFT_REPEAT(state_value) \
|
|
184
|
+
{{ \
|
|
185
|
+
.shift = { \
|
|
186
|
+
.type = TSParseActionTypeShift, \
|
|
187
|
+
.state = state_value, \
|
|
188
|
+
.repetition = true \
|
|
189
|
+
} \
|
|
190
|
+
}}
|
|
191
|
+
|
|
192
|
+
#define SHIFT_EXTRA() \
|
|
193
|
+
{{ \
|
|
194
|
+
.shift = { \
|
|
195
|
+
.type = TSParseActionTypeShift, \
|
|
196
|
+
.extra = true \
|
|
197
|
+
} \
|
|
198
|
+
}}
|
|
199
|
+
|
|
200
|
+
#define REDUCE(symbol_val, child_count_val, ...) \
|
|
201
|
+
{{ \
|
|
202
|
+
.reduce = { \
|
|
203
|
+
.type = TSParseActionTypeReduce, \
|
|
204
|
+
.symbol = symbol_val, \
|
|
205
|
+
.child_count = child_count_val, \
|
|
206
|
+
__VA_ARGS__ \
|
|
207
|
+
}, \
|
|
208
|
+
}}
|
|
209
|
+
|
|
210
|
+
#define RECOVER() \
|
|
211
|
+
{{ \
|
|
212
|
+
.type = TSParseActionTypeRecover \
|
|
213
|
+
}}
|
|
214
|
+
|
|
215
|
+
#define ACCEPT_INPUT() \
|
|
216
|
+
{{ \
|
|
217
|
+
.type = TSParseActionTypeAccept \
|
|
218
|
+
}}
|
|
219
|
+
|
|
220
|
+
#ifdef __cplusplus
|
|
221
|
+
}
|
|
222
|
+
#endif
|
|
223
|
+
|
|
224
|
+
#endif // TREE_SITTER_PARSER_H_
|
data/exe/demotape
CHANGED
data/lib/demo_tape/cli.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "thor"
|
|
4
|
+
require_relative "ext/thor"
|
|
4
5
|
require "thor/completion"
|
|
5
6
|
|
|
6
7
|
module DemoTape
|
|
@@ -144,8 +145,15 @@ module DemoTape
|
|
|
144
145
|
|
|
145
146
|
if file_path == ""
|
|
146
147
|
file_path = "<stdin>"
|
|
147
|
-
|
|
148
|
-
|
|
148
|
+
|
|
149
|
+
if $stdin.tty?
|
|
150
|
+
help
|
|
151
|
+
exit 1
|
|
152
|
+
else
|
|
153
|
+
content = $stdin.read
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
options[:output_path] = ["stdin.mp4"] if options.output_path.empty?
|
|
149
157
|
else
|
|
150
158
|
content = File.read(file_path)
|
|
151
159
|
end
|
data/lib/demo_tape/command.rb
CHANGED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "thor/parser/argument"
|
|
4
|
+
|
|
5
|
+
class Thor
|
|
6
|
+
class Argument
|
|
7
|
+
def print_default
|
|
8
|
+
if (@type == :array) && @default.is_a?(Array)
|
|
9
|
+
@default.map do |item|
|
|
10
|
+
item.respond_to?(:dump) ? item.dump : item
|
|
11
|
+
end.join(" ")
|
|
12
|
+
else
|
|
13
|
+
@default
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
data/lib/demo_tape/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: demotape
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Nando Vieira
|
|
@@ -267,18 +267,38 @@ files:
|
|
|
267
267
|
- demotape.jsonc
|
|
268
268
|
- demotape.y
|
|
269
269
|
- demotape_ascii.rb
|
|
270
|
-
- demotape_new.y.backup
|
|
271
|
-
- demotape_simple_test.y
|
|
272
270
|
- editors/sublime-text/Comments (DemoTape).tmPreferences
|
|
273
271
|
- editors/sublime-text/DemoTape.sublime-completions
|
|
274
272
|
- editors/sublime-text/DemoTape.sublime-syntax
|
|
275
273
|
- editors/vim/README.md
|
|
276
274
|
- editors/vim/ftdetect/demotape.vim
|
|
277
275
|
- editors/vim/syntax/demotape.vim
|
|
276
|
+
- editors/vscode/LICENSE.md
|
|
278
277
|
- editors/vscode/README.md
|
|
278
|
+
- editors/vscode/RELEASE_PROCESS.md
|
|
279
279
|
- editors/vscode/demotape.tmLanguage.json
|
|
280
|
+
- editors/vscode/icon.png
|
|
280
281
|
- editors/vscode/language-configuration.json
|
|
281
282
|
- editors/vscode/package.json
|
|
283
|
+
- editors/zed/extension.toml
|
|
284
|
+
- editors/zed/grammars/demotape.wasm
|
|
285
|
+
- editors/zed/languages/demotape/config.toml
|
|
286
|
+
- editors/zed/languages/demotape/highlights.scm
|
|
287
|
+
- editors/zed/package-lock.json
|
|
288
|
+
- editors/zed/tree-sitter/Cargo.toml
|
|
289
|
+
- editors/zed/tree-sitter/binding.gyp
|
|
290
|
+
- editors/zed/tree-sitter/bindings/node/binding.cc
|
|
291
|
+
- editors/zed/tree-sitter/bindings/node/index.js
|
|
292
|
+
- editors/zed/tree-sitter/bindings/rust/build.rs
|
|
293
|
+
- editors/zed/tree-sitter/bindings/rust/lib.rs
|
|
294
|
+
- editors/zed/tree-sitter/grammar.js
|
|
295
|
+
- editors/zed/tree-sitter/package-lock.json
|
|
296
|
+
- editors/zed/tree-sitter/package.json
|
|
297
|
+
- editors/zed/tree-sitter/queries/highlights.scm
|
|
298
|
+
- editors/zed/tree-sitter/src/grammar.json
|
|
299
|
+
- editors/zed/tree-sitter/src/node-types.json
|
|
300
|
+
- editors/zed/tree-sitter/src/parser.c
|
|
301
|
+
- editors/zed/tree-sitter/src/tree_sitter/parser.h
|
|
282
302
|
- exe/demotape
|
|
283
303
|
- lib/demo_tape.rb
|
|
284
304
|
- lib/demo_tape/bounds.rb
|
|
@@ -286,6 +306,7 @@ files:
|
|
|
286
306
|
- lib/demo_tape/command.rb
|
|
287
307
|
- lib/demo_tape/duration.rb
|
|
288
308
|
- lib/demo_tape/exporter.rb
|
|
309
|
+
- lib/demo_tape/ext/thor.rb
|
|
289
310
|
- lib/demo_tape/formatter.rb
|
|
290
311
|
- lib/demo_tape/generator.rb
|
|
291
312
|
- lib/demo_tape/lexer.rb
|
|
@@ -670,10 +691,10 @@ metadata:
|
|
|
670
691
|
rubygems_mfa_required: 'true'
|
|
671
692
|
homepage_uri: https://github.com/fnando/demotape
|
|
672
693
|
bug_tracker_uri: https://github.com/fnando/demotape/issues
|
|
673
|
-
source_code_uri: https://github.com/fnando/demotape/tree/v0.0.
|
|
674
|
-
changelog_uri: https://github.com/fnando/demotape/tree/v0.0.
|
|
675
|
-
documentation_uri: https://github.com/fnando/demotape/tree/v0.0.
|
|
676
|
-
license_uri: https://github.com/fnando/demotape/tree/v0.0.
|
|
694
|
+
source_code_uri: https://github.com/fnando/demotape/tree/v0.0.4
|
|
695
|
+
changelog_uri: https://github.com/fnando/demotape/tree/v0.0.4/CHANGELOG.md
|
|
696
|
+
documentation_uri: https://github.com/fnando/demotape/tree/v0.0.4/README.md
|
|
697
|
+
license_uri: https://github.com/fnando/demotape/tree/v0.0.4/LICENSE.md
|
|
677
698
|
rdoc_options: []
|
|
678
699
|
require_paths:
|
|
679
700
|
- lib
|
data/demotape_new.y.backup
DELETED
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
class DemoTape::Parser
|
|
2
|
-
rule
|
|
3
|
-
# Top level: document is a flat list of tokens and contexts
|
|
4
|
-
document: items { result = val[0].flatten.compact }
|
|
5
|
-
| /* empty */ { result = [] }
|
|
6
|
-
|
|
7
|
-
items: item { result = [val[0]] }
|
|
8
|
-
| items item { result = val[0] << val[1] }
|
|
9
|
-
|
|
10
|
-
# An item can be a token or a context
|
|
11
|
-
item: COMMENT { result = make_token(:comment, val[0], @token_index - 1) }
|
|
12
|
-
| NEWLINE { result = make_token(:newline, val[0], @token_index - 1) }
|
|
13
|
-
| LEADING_SPACE { result = make_token(:leading_space, val[0], @token_index - 1) }
|
|
14
|
-
| TRAILING_SPACE { result = make_token(:trailing_space, val[0], @token_index - 1) }
|
|
15
|
-
| command_line { result = val[0] }
|
|
16
|
-
| group_context { result = val[0] }
|
|
17
|
-
|
|
18
|
-
# A command line: tokens terminated by newline
|
|
19
|
-
command_line: command_tokens NEWLINE {
|
|
20
|
-
result = [{
|
|
21
|
-
type: :command,
|
|
22
|
-
tokens: val[0],
|
|
23
|
-
line: line_for_token_at(@command_start_index),
|
|
24
|
-
column: column_for_token_at(@command_start_index)
|
|
25
|
-
}, make_token(:newline, val[1], @token_index - 1)]
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
leading_space: LEADING_SPACE { result = make_token(:leading_space, val[0], @token_index - 1) }
|
|
29
|
-
|
|
30
|
-
trailing_space: TRAILING_SPACE { result = make_token(:trailing_space, val[0], @token_index - 1) }
|
|
31
|
-
|
|
32
|
-
# Group context: Group name do ... end
|
|
33
|
-
group_context: IDENTIFIER SPACE IDENTIFIER SPACE DO NEWLINE group_body END {
|
|
34
|
-
@command_start_index = @token_index - 8
|
|
35
|
-
result = {
|
|
36
|
-
type: :group,
|
|
37
|
-
name: val[2],
|
|
38
|
-
tokens: [
|
|
39
|
-
make_token(:identifier, val[0], @token_index - 8),
|
|
40
|
-
make_token(:space, val[1], @token_index - 7),
|
|
41
|
-
make_token(:identifier, val[2], @token_index - 6),
|
|
42
|
-
make_token(:space, val[3], @token_index - 5),
|
|
43
|
-
make_token(:keyword, "do", @token_index - 4)
|
|
44
|
-
],
|
|
45
|
-
body: val[6],
|
|
46
|
-
line: line_for_token_at(@token_index - 8),
|
|
47
|
-
column: column_for_token_at(@token_index - 8)
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
group_body: /* empty */ { result = [] }
|
|
52
|
-
| group_body item { result = val[0] << val[1] }
|
|
53
|
-
|
|
54
|
-
# Command tokens: any sequence of tokens until newline
|
|
55
|
-
command_tokens: command_token { @command_start_index = @token_index - 1; result = [val[0]] }
|
|
56
|
-
| command_tokens SPACE command_token { result = val[0] << make_token(:space, val[1], @token_index - 2) << val[2] }
|
|
57
|
-
| command_tokens optional_space COMMA optional_space command_token {
|
|
58
|
-
result = val[0]
|
|
59
|
-
result << make_token(:space, val[1], @token_index - 4) if val[1]
|
|
60
|
-
result << make_token(:operator, ",", @token_index - 3)
|
|
61
|
-
result << make_token(:space, val[3], @token_index - 2) if val[3]
|
|
62
|
-
result << val[4]
|
|
63
|
-
}
|
|
64
|
-
| command_tokens PLUS command_token {
|
|
65
|
-
result = val[0] << make_token(:operator, "+", @token_index - 2) << val[2]
|
|
66
|
-
}
|
|
67
|
-
| command_tokens AT duration {
|
|
68
|
-
result = val[0] << make_token(:operator, "@", @token_index - 2) << val[2]
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
optional_space: SPACE { result = val[0] }
|
|
72
|
-
| /* empty */ { result = nil }
|
|
73
|
-
|
|
74
|
-
command_token: IDENTIFIER { result = make_token(:identifier, val[0], @token_index - 1) }
|
|
75
|
-
| STRING { result = make_token(:string, val[0], @token_index - 1) }
|
|
76
|
-
| NUMBER { result = make_token(:number, val[0], @token_index - 1) }
|
|
77
|
-
| REGEX { result = make_token(:regex, val[0], @token_index - 1) }
|
|
78
|
-
|
|
79
|
-
duration: NUMBER TIME_UNIT {
|
|
80
|
-
result = make_token(:duration, "#{val[0]}#{val[1]}", @token_index - 2)
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
---- header
|
|
84
|
-
require_relative "token"
|
|
85
|
-
require_relative "lexer"
|
|
86
|
-
require_relative "ast"
|
|
87
|
-
|
|
88
|
-
---- inner
|
|
89
|
-
def parse(str, file: "<unknown>")
|
|
90
|
-
@file = file
|
|
91
|
-
@lexer = DemoTape::Lexer.new
|
|
92
|
-
@tokens = @lexer.tokenize(str)
|
|
93
|
-
@token_index = 0
|
|
94
|
-
do_parse
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
def next_token
|
|
98
|
-
token = @tokens.shift
|
|
99
|
-
@current_token_index = @token_index
|
|
100
|
-
@token_index += 1
|
|
101
|
-
token
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
def make_token(type, value, index)
|
|
105
|
-
line_info = @lexer.line_map[index] || {}
|
|
106
|
-
token_class = case type
|
|
107
|
-
when :identifier then DemoTape::Token::Identifier
|
|
108
|
-
when :string then DemoTape::Token::String
|
|
109
|
-
when :number then DemoTape::Token::Number
|
|
110
|
-
when :duration then DemoTape::Token::Duration
|
|
111
|
-
when :regex then DemoTape::Token::Regex
|
|
112
|
-
when :time_unit then DemoTape::Token::TimeUnit
|
|
113
|
-
when :operator then DemoTape::Token::Operator
|
|
114
|
-
when :space then DemoTape::Token::Space
|
|
115
|
-
when :leading_space then DemoTape::Token::LeadingSpace
|
|
116
|
-
when :trailing_space then DemoTape::Token::TrailingSpace
|
|
117
|
-
when :keyword then DemoTape::Token::Keyword
|
|
118
|
-
when :comment then DemoTape::Token::Comment
|
|
119
|
-
when :newline then DemoTape::Token::Newline
|
|
120
|
-
else DemoTape::Token::Base
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
token_class.new(
|
|
124
|
-
value,
|
|
125
|
-
line: line_info[:line],
|
|
126
|
-
column: line_info[:column],
|
|
127
|
-
raw: line_info[:raw]
|
|
128
|
-
)
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
def line_for_token_at(index)
|
|
132
|
-
line_info = @lexer.line_map[index] || {}
|
|
133
|
-
line_info[:line]
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
def column_for_token_at(index)
|
|
137
|
-
line_info = @lexer.line_map[index] || {}
|
|
138
|
-
line_info[:column]
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
def collect_tokens(*values)
|
|
142
|
-
values.flatten.compact.select { |v| v.is_a?(DemoTape::Token::Base) }
|
|
143
|
-
end
|
|
144
|
-
|
|
145
|
-
def on_error(token_id, token_value, value_stack)
|
|
146
|
-
line_info = @lexer.line_map[@current_token_index] || {}
|
|
147
|
-
line_num = line_info[:line] || "?"
|
|
148
|
-
col_num = line_info[:column] || 1
|
|
149
|
-
line_content = line_info[:content] || ""
|
|
150
|
-
|
|
151
|
-
token_name = token_to_str(token_id) || token_id.to_s
|
|
152
|
-
|
|
153
|
-
error_msg = "Unexpected token #{token_name.inspect} at #{@file}:#{line_num}:#{col_num}:\n"
|
|
154
|
-
error_msg += " #{line_content.strip}\n"
|
|
155
|
-
error_msg += " #{' ' * (col_num - line_content.length + line_content.strip.length - 1)}^"
|
|
156
|
-
|
|
157
|
-
raise DemoTape::ParseError, error_msg
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
---- footer
|
data/demotape_simple_test.y
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
class DemoTape::SimpleParser
|
|
2
|
-
rule
|
|
3
|
-
# Match lines - each line is either comment+newline or command tokens+newline
|
|
4
|
-
document: lines { result = val[0].flatten }
|
|
5
|
-
| /* empty */ { result = [] }
|
|
6
|
-
|
|
7
|
-
lines: line { result = [val[0]] }
|
|
8
|
-
| lines line { result = val[0] + val[1] }
|
|
9
|
-
|
|
10
|
-
# A line ends with NEWLINE
|
|
11
|
-
line: COMMENT NEWLINE { result = [[:comment, val[0]], [:newline, val[1]]] }
|
|
12
|
-
| NEWLINE { result = [[:newline, val[0]]] }
|
|
13
|
-
| line_tokens NEWLINE { result = [{ type: :command, tokens: val[0] }, [:newline, val[1]]] }
|
|
14
|
-
|
|
15
|
-
# Line tokens: anything that's not a newline
|
|
16
|
-
line_tokens: line_token { result = [val[0]] }
|
|
17
|
-
| line_tokens line_token { result = val[0] << val[1] }
|
|
18
|
-
|
|
19
|
-
line_token: IDENTIFIER { result = [:id, val[0]] }
|
|
20
|
-
| STRING { result = [:str, val[0]] }
|
|
21
|
-
| SPACE { result = [:sp, val[0]] }
|
|
22
|
-
| LEADING_SPACE { result = [:lsp, val[0]] }
|
|
23
|
-
|
|
24
|
-
---- inner
|
|
25
|
-
def parse(tokens)
|
|
26
|
-
@tokens = tokens
|
|
27
|
-
do_parse
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def next_token
|
|
31
|
-
@tokens.shift
|
|
32
|
-
end
|