diff options
Diffstat (limited to 'grammar.js')
| -rw-r--r-- | grammar.js | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/grammar.js b/grammar.js new file mode 100644 index 0000000..e35473f --- /dev/null +++ b/grammar.js @@ -0,0 +1,133 @@ +/** + * @file Parser for wmap Formatted Wardley Maps + * @author Rubén Beltrán del Río <wmap.parser@r.bdr.sh> + * @license AGPL-v3 + */ + +/// <reference types="tree-sitter-cli/dsl" /> +// @ts-check + +export default grammar({ + name: "wmap", + + extras: $ => [/[ \t]/], + + rules: { + source_file: $ => repeat( + choice( + seq($.entity, $._line_ending), + $._line_ending + ) + ), + + entity: $ => choice( + $.component, + $.dependency, + $.note, + $.stage, + $.group, + $.inertia, + $.evolution, + ), + + // Entities + component: $ => seq( + field('label', $.component_label), + field('position', $.position), + optional(field('shape', $.shape)) + ), + + dependency: $ => seq( + field('from', $.component_label), + field('type', $.dependency_type), + field('to', $.component_label) + ), + + note: $ => seq( + alias($._note_keyword, 'keyword'), + field('position', $.position), + field('text', $.text) + ), + + stage: $ => seq( + '[', + field('number', $.stage_number), + ']', + field('value', $.real_number) + ), + + group: $ => seq( + alias($._group_keyword, 'keyword'), + field('component', $.component_label), + repeat(seq(',', field('component', $.component_label))) + ), + + inertia: $ => seq( + alias($._inertia_keyword, 'keyword'), + field('component', $.component_label) + ), + + evolution: $ => seq( + alias($._evolution_keyword, 'keyword'), + field('component', $.component_label), + field('sign', $.sign), + field('value', $.real_number) + ), + + // Component definitions + position: $ => seq( + '(', + field('x', $.real_number), + ',', + field('y', $.real_number), + ')' + ), + + shape: $ => seq( + '[', + $.shape_label, + ']' + ), + + dependency_type: $ => choice('--', '->'), + + sign: $ => choice('+', '-'), + + component_label: $ => /[^\-+,\[\]()\n\r]+/, + + text: $ => /[^\n\r]+/, + + real_number: $ => choice( + /[0-9]+\.[0-9]*/, + /[0-9]+/, + /\.[0-9]+/ + ), + + stage_number: $ => choice( + /[Ii][Vv]/, // IV (must come before single I) + /[Ii][Ii][Ii]/, // III + /[Ii][Ii]/, // II + /[Ii]/ // I + ), + + shape_label: $ => choice( + /[Xx]/, + /[Ss][Qq][Uu][Aa][Rr][Ee]/, + /[Tt][Rr][Ii][Aa][Nn][Gg][Ll][Ee]/, + /[Cc][Ii][Rr][Cc][Ll][Ee]/ + ), + + // Keywords (case-insensitive) + _note_keyword: $ => /\[[Nn][Oo][Tt][Ee]\]/, + _group_keyword: $ => /\[[Gg][Rr][Oo][Uu][Pp]\]/, + _inertia_keyword: $ => /\[[Ii][Nn][Ee][Rr][Tt][Ii][Aa]\]/, + _evolution_keyword: $ => /\[[Ee][Vv][Oo][Ll][Uu][Tt][Ii][Oo][Nn]\]/, + + // Line endings (Unix LF, Windows CRLF, classic Mac CR) + _line_ending: $ => choice( + '\n', // LF + '\r\n', // CRLF + '\r' // CR + ), + } +}); |