├── LICENSE ├── README.md ├── am-lua-5.4.6.c ├── am-lua-5.4.6.js ├── am-lua-5.4.6.wasm ├── examples ├── ada.ebnf ├── angular.ebnf ├── awk.ebnf ├── bash.ebnf ├── bison.ebnf ├── c.ebnf ├── c11-ast-playground.lua ├── cmake.ebnf ├── commonlisp.ebnf ├── cpp.ebnf ├── csharp.ebnf ├── css.ebnf ├── cvt-tree-sitter-grammars.sh ├── d.ebnf ├── dart.ebnf ├── dockerfile.ebnf ├── elixir.ebnf ├── elm.ebnf ├── erlang.ebnf ├── fact.c ├── fact.lua ├── fortran.ebnf ├── fsharp.ebnf ├── gleam.ebnf ├── go.ebnf ├── haskell.ebnf ├── haxe.ebnf ├── html.ebnf ├── java.ebnf ├── javascript.ebnf ├── json-ast-playground.lua ├── julia.ebnf ├── kotlin.ebnf ├── ld.ebnf ├── lean.ebnf ├── lua-ast-playground.lua ├── lua.ebnf ├── make.ebnf ├── markdown.ebnf ├── minizinc.ebnf ├── nim2.ebnf ├── ocaml.ebnf ├── php.ebnf ├── python.ebnf ├── regex.ebnf ├── ruby.ebnf ├── rust.ebnf ├── sample.json.txt ├── scala.ebnf ├── schemasafe.qjs ├── simple.lua ├── sql.ebnf ├── squirrel.ebnf ├── swift.ebnf ├── teal.ebnf ├── tlaplus.ebnf ├── tree-sitter-ebnf-generator-cmd.lua ├── tree-sitter-ebnf-generator.lua ├── tree-sitter-json-schema.json ├── typescript.ebnf ├── v-analyzer.ebnf ├── v.ebnf ├── vimdoc.ebnf ├── vimscript.ebnf └── zig.ebnf ├── index.html ├── index.js ├── lua-playground.c ├── mk-lua-amalgamation.lua ├── mk-wasm.sh └── style.css /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Domingo Alvarez Duarte 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # A web playground with Lua interpreter compiled to wasm 2 | 3 | Here is an amalgamation of Lua 5.4.6, https://github.com/sqmedeiros/lpeglabel and https://github.com/edubart/lpegrex compiled to wasm that can be viewed at https://mingodad.github.io/lua-wasm-playground/ . 4 | 5 | The playground website is based on https://yhirose.github.io/cpp-peglib/ and also with modifications based on https://chrishixon.github.io/chpeg/playground/ . 6 | -------------------------------------------------------------------------------- /am-lua-5.4.6.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mingodad/lua-wasm-playground/247c2004492b8de664cea6cc731283b725318db5/am-lua-5.4.6.wasm -------------------------------------------------------------------------------- /examples/angular.ebnf: -------------------------------------------------------------------------------- 1 | ; repository: https://github.com/dlvandenberg/tree-sitter-angular.git 2 | ; commit: c473dbc54ca27f95d8928cfdb2a1a79300e16951 3 | ; json from: tree-sitter-angular/src/grammar.json 4 | ; From /tmp/tslua/angular0.json 5 | ; EBNF to generate grammar.js at 6 | ; https://mingodad.github.io/lua-wasm-playground/ 7 | ; based on https://github.com/eatkins/tree-sitter-ebnf-generator 8 | ; see also https://mingodad.github.io/plgh/json2ebnf.html 9 | 10 | 11 | externals ::= { 12 | _start_tag_name 13 | _script_start_tag_name 14 | _style_start_tag_name 15 | _end_tag_name 16 | erroneous_end_tag_name 17 | '/>' 18 | _implicit_end_tag 19 | raw_text 20 | comment 21 | _interpolation_start 22 | _interpolation_end 23 | _control_flow_start 24 | } 25 | 26 | extras ::= { 27 | comment 28 | /\s+/ 29 | } 30 | 31 | rules: 32 | 33 | document ::= _node* 34 | 35 | doctype ::= ' "doctype" /[^>]+/ '>' 36 | 37 | _doctype ::= /[Dd][Oo][Cc][Tt][Yy][Pp][Ee]/ 38 | 39 | _node ::= 1( icu_expression ) 40 | | 1( interpolation ) 41 | | 1( _any_statement ) 42 | | doctype 43 | | entity 44 | | text 45 | | element 46 | | script_element 47 | | style_element 48 | | erroneous_end_tag 49 | 50 | element ::= start_tag _node* ( end_tag | _implicit_end_tag ) 51 | | self_closing_tag 52 | 53 | script_element ::= script_start_tag -> start_tag raw_text? end_tag 54 | 55 | style_element ::= style_start_tag -> start_tag raw_text? end_tag 56 | 57 | start_tag ::= '<' _start_tag_name -> tag_name attribute* '>' 58 | 59 | script_start_tag ::= '<' _script_start_tag_name -> tag_name attribute* '>' 60 | 61 | style_start_tag ::= '<' _style_start_tag_name -> tag_name attribute* '>' 62 | 63 | self_closing_tag ::= '<' _start_tag_name -> tag_name attribute* '/>' 64 | 65 | end_tag ::= ' tag_name '>' 66 | 67 | erroneous_end_tag ::= '' 68 | 69 | attribute ::= 1( property_binding ) 70 | | 1( two_way_binding ) 71 | | 1( animation_binding ) 72 | | 1( event_binding ) 73 | | 1( structural_directive ) 74 | | _normal_attribute 75 | 76 | attribute_name ::= /[^<>\*.\[\]\(\)"'=\s]+/ 77 | 78 | attribute_value ::= /[^<>"'=\s]+/ 79 | 80 | entity ::= /&(#([xX][0-9a-fA-F]{1,6}|[0-9]{1,5})|[A-Za-z]{1,30});?/ 81 | 82 | quoted_attribute_value ::= "'" ( /[^']+/ -> attribute_value )? "'" 83 | | '"' ( /[^"]+/ -> attribute_value )? '"' 84 | 85 | text ::= /[^<>{}&\s]([^<>{}&]*[^<>{}&\s])?/ 86 | 87 | statement_block ::= >0( '{' _node* '}' ) 88 | 89 | _any_statement ::= if_statement 90 | | for_statement 91 | | defer_statement 92 | | switch_statement 93 | | _alternative_statement 94 | 95 | _alternative_statement ::= else_statement:alternative 96 | | else_if_statement:alternative_condition 97 | | empty_statement:empty 98 | | placeholder_statement:placeholder 99 | | loading_statement:loading 100 | | error_statement:error 101 | 102 | switch_statement ::= >0( _control_flow_start -> "@" 'switch' -> control_keyword '(' expression:value ')' switch_body:body ) 103 | 104 | switch_body ::= '{' ( case_statement | default_statement )+ '}' 105 | 106 | case_statement ::= _control_flow_start -> "@" 'case' -> control_keyword '(' _primitive:value ')' statement_block:body 107 | 108 | default_statement ::= _control_flow_start -> "@" 'default' -> control_keyword statement_block:body 109 | 110 | defer_statement ::= <0( _control_flow_start -> "@" 'defer' -> control_keyword defer_trigger? statement_block:body ) 111 | 112 | placeholder_statement ::= <0( _control_flow_start -> "@" 'placeholder' -> control_keyword placeholder_minimum? statement_block:body ) 113 | 114 | loading_statement ::= <0( _control_flow_start -> "@" 'loading' -> control_keyword loading_condition? statement_block:body ) 115 | 116 | error_statement ::= _control_flow_start -> "@" 'error' -> control_keyword statement_block:body 117 | 118 | defer_trigger ::= '(' defer_trigger_condition:condition ( ';' defer_trigger_condition:condition )*? ')' 119 | 120 | placeholder_minimum ::= '(' timed_expression:minimum ')' 121 | 122 | loading_condition ::= '(' timed_expression:condition ( ';' timed_expression:condition )? ')' 123 | 124 | defer_trigger_condition ::= ( 'prefetch' -> prefetch_keyword )? ( 'when' -> special_keyword _any_expression:trigger | 'on' -> special_keyword _primitive:trigger ) 125 | 126 | timed_expression ::= ( 'after' | 'minimum' ) -> special_keyword number:value ( 'ms' | 's' ) -> unit 127 | 128 | for_statement ::= <0( _control_flow_start -> "@" 'for' -> control_keyword '(' for_declaration:declaration ( for_reference:reference )? ')' statement_block:body ) 129 | 130 | empty_statement ::= _control_flow_start -> "@" 'empty' -> control_keyword statement_block:body 131 | 132 | for_declaration ::= identifier:name 'of' -> special_keyword expression:value ';' 'track' -> special_keyword expression:track 133 | 134 | for_reference ::= ';' 'let' -> special_keyword assignment_expression:alias ( ( ';' | ',' ) assignment_expression:alias )* 135 | 136 | if_statement ::= >0( _if_start_expression _if_body_expression ) 137 | 138 | else_if_statement ::= >0( _else_if_start_expression _if_body_expression ) 139 | 140 | else_statement ::= >0( _control_flow_start -> "@" 'else' -> control_keyword statement_block ) 141 | 142 | _if_start_expression ::= _control_flow_start -> "@" 'if' -> control_keyword 143 | 144 | _else_if_start_expression ::= _control_flow_start -> "@" 'else' -> control_keyword 'if' -> control_keyword 145 | 146 | _if_body_expression ::= <0( '(' if_condition:condition ( if_reference:reference )? ')' statement_block:consequence ) 147 | 148 | if_condition ::= >1( _any_expression ) 149 | 150 | if_reference ::= ';' 'as' -> special_keyword identifier 151 | 152 | _any_expression ::= binary_expression 153 | | unary_expression 154 | | expression 155 | | ternary_expression 156 | | nullish_coalescing_expression 157 | | 3( conditional_expression ) 158 | 159 | assignment_expression ::= identifier:name '=' _any_expression:value 160 | 161 | icu_expression ::= '{' ( _any_expression | concatenation_expression ) ',' icu_clause ',' icu_case+ '}' 162 | 163 | icu_clause ::= 'plural' 164 | | 'select' 165 | 166 | icu_case ::= icu_category '{' _node+ '}' 167 | 168 | icu_category ::= /[^{}]+/i 169 | 170 | interpolation ::= _interpolation_start -> "{{" ( _any_expression | concatenation_expression ) _interpolation_end -> "}}" 171 | 172 | concatenation_expression ::= 2( _primitive '+' expression ( '+' _primitive )*? ) 173 | 174 | structural_directive ::= '*' identifier ( '=' _double_quote ( structural_expression | structural_declaration ) _double_quote )? 175 | 176 | structural_expression ::= _any_expression _alias? _else_template_expression? _context_expression? 177 | 178 | structural_declaration ::= 'let' -> special_keyword structural_assignment ( ( ';' | ',' ) structural_assignment )* 179 | 180 | structural_assignment ::= identifier:name ':' identifier:value 181 | | <2( ( 'let' -> special_keyword )? identifier:name ( identifier | '=' ):operator expression:value _alias? ) 182 | | identifier:name _alias? 183 | 184 | _alias ::= 'as' -> special_keyword identifier:alias 185 | 186 | _else_template_expression ::= ';' 'else' -> special_keyword identifier 187 | 188 | _context_expression ::= ';' ( 'context' -> special_keyword | identifier:named ) ':' _any_expression 189 | 190 | property_binding ::= '[' binding_name ']' _binding_assignment 191 | 192 | event_binding ::= '(' binding_name ')' _binding_assignment 193 | 194 | two_way_binding ::= '[(' binding_name ')]' _binding_assignment 195 | 196 | animation_binding ::= '[@' binding_name ']' ( _binding_assignment:trigger )? 197 | 198 | _binding_assignment ::= '=' _double_quote ( _any_expression | assignment_expression )? _double_quote 199 | 200 | binding_name ::= ( identifier | member_expression ) 201 | 202 | _normal_attribute ::= attribute_name ( '=' ( attribute_value | quoted_attribute_value ) )? 203 | 204 | expression ::= _primitive ( pipe_sequence:pipes )? 205 | 206 | unary_expression ::= ( '!' -> unary_operator ):operator expression:value 207 | 208 | binary_expression ::= <1( expression:left _binary_op:operator ( binary_expression | expression ):right ) 209 | 210 | ternary_expression ::= >1( _any_expression:condition '?' -> ternary_operator ( group | _primitive ):consequence ':' -> ternary_operator ( group | _any_expression ):alternative ) 211 | 212 | nullish_coalescing_expression ::= _any_expression:condition '??' -> coalescing_operator _primitive:default 213 | 214 | conditional_expression ::= >1( ( _primitive | unary_expression | binary_expression ):left ( '||' | '&&' ) -> conditional_operator ( _primitive | unary_expression | binary_expression | conditional_expression ):right ) 215 | 216 | pipe_sequence ::= ( '|' -> pipe_operator pipe_call )+ 217 | 218 | pipe_call ::= identifier:name ( pipe_arguments:arguments )? 219 | 220 | pipe_arguments ::= _pipe_argument+ 221 | 222 | _pipe_argument ::= ':' _primitive 223 | 224 | _primitive ::= object 225 | | array 226 | | identifier 227 | | string 228 | | number 229 | | group 230 | | call_expression 231 | | member_expression 232 | | bracket_expression 233 | 234 | object ::= '{' pair* '}' 235 | 236 | pair ::= ( identifier | string ):key ':' _any_expression:value ','? 237 | 238 | array ::= '[' ( expression | unary_expression ) ( ',' ( expression | unary_expression ) )* ']' 239 | 240 | identifier ::= /[a-zA-Z_0-9\-\$]+/ 241 | 242 | string ::= _double_quote !( /[^"]/ )* _double_quote 243 | | _single_quote !( /[^']/ )* _single_quote 244 | 245 | number ::= /[0-9]+\.?[0-9]*/ 246 | 247 | group ::= '(' _any_expression ')' 248 | 249 | call_expression ::= <1( identifier:function '(' ( arguments:arguments )? ')' ) 250 | 251 | arguments ::= ( _primitive | binary_expression | unary_expression ) ( ',' _primitive )* 252 | 253 | member_expression ::= _primitive:object ( ( '.' | '?.' | '!.' ) ( identifier:property | call_expression:call ) ) 254 | 255 | bracket_expression ::= <1( _primitive:object '[' ( identifier | static_member_expression ):property ']' ) 256 | 257 | static_member_expression ::= _single_quote identifier _single_quote 258 | 259 | _closing_bracket ::= @( -1( '}' ) ) 260 | 261 | _single_quote ::= "'" 262 | 263 | _double_quote ::= '"' 264 | 265 | _binary_op ::= '+' 266 | | '-' 267 | | '/' 268 | | '*' 269 | | '%' 270 | | '==' 271 | | '===' 272 | | '!=' 273 | | '!==' 274 | | '&&' 275 | | '||' 276 | | '<' 277 | | '<=' 278 | | '>' 279 | | '>=' 280 | 281 | -------------------------------------------------------------------------------- /examples/awk.ebnf: -------------------------------------------------------------------------------- 1 | ; repository: https://github.com/Beaglefoot/tree-sitter-awk.git 2 | ; commit: ba7472152d79a8c916550c80fdbfd5724d07a0c9 3 | ; json from: tree-sitter-awk/src/grammar.json 4 | ; From /tmp/tslua/awk0.json 5 | ; EBNF to generate grammar.js at 6 | ; https://mingodad.github.io/lua-wasm-playground/ 7 | ; based on https://github.com/eatkins/tree-sitter-ebnf-generator 8 | ; see also https://mingodad.github.io/plgh/json2ebnf.html 9 | 10 | 11 | externals ::= { 12 | concatenating_space 13 | _if_else_separator 14 | _no_space 15 | } 16 | 17 | extras ::= { 18 | /[\s\t]/ 19 | '\\\n' 20 | '\\\r\n' 21 | } 22 | 23 | precedences ::= { 24 | ;;10 25 | { getline_file getline_input grouping field_ref func_call update_exp 'binary_exponent' 'binary_times' 'binary_plus' string_concat unary_exp 'binary_relation' 'binary_match' _binary_in 'binary_and' 'binary_or' ternary_exp exp_list piped_io_exp range_pattern _statement } 26 | ;;09 27 | { func_call _exp } 28 | ;;08 29 | { update_exp _exp } 30 | ;;07 31 | { if_statement _statement_separated } 32 | ;;06 33 | { else_clause _statement_separated } 34 | ;;05 35 | { print_statement printf_statement grouping } 36 | ;;04 37 | { _print_args grouping piped_io_exp 'binary_relation' } 38 | ;;03 39 | { for_in_statement _exp } 40 | ;;02 41 | { _exp string_concat assignment_exp } 42 | ;;01 43 | { _print_args _binary_in } 44 | } 45 | 46 | word ::= identifier 47 | 48 | rules: 49 | 50 | program ::= ( rule | func_def | directive | comment )* 51 | 52 | rule ::= >0( pattern block? | pattern? block ) 53 | 54 | pattern ::= >0( _exp | range_pattern | _special_pattern ) 55 | 56 | range_pattern ::= _exp:start ',' _exp:stop 57 | 58 | _special_pattern ::= 'BEGIN' 59 | | 'END' 60 | | 'BEGINFILE' 61 | | 'ENDFILE' 62 | 63 | directive ::= ( '@include' | '@load' | '@namespace' ) string 64 | 65 | _statement ::= <0( _statement_separated _statement | _statement_separated | _control_statement | _io_statement | _exp ) 66 | 67 | _statement_separated ::= >0( _statement ( ';' | '\n' | '\r\n' ) ) 68 | 69 | _control_statement ::= if_statement 70 | | while_statement 71 | | do_while_statement 72 | | for_statement 73 | | for_in_statement 74 | | break_statement 75 | | continue_statement 76 | | delete_statement 77 | | exit_statement 78 | | return_statement 79 | | switch_statement 80 | 81 | if_statement ::= >0( 'if' ( '(' _exp ')' ):condition comment* ( block | _statement | ';' ) ( _if_else_separator comment* else_clause )? ) 82 | 83 | else_clause ::= 'else' ( block | _statement ) 84 | 85 | while_statement ::= >0( 'while' ( '(' _exp ')' ):condition comment* ( block | _statement | ';' ) ) 86 | 87 | do_while_statement ::= >0( 'do' comment* ( block | _statement ) 'while' ( '(' _exp ')' ):condition ) 88 | 89 | for_statement ::= >0( 'for' '(' _exp?:initializer ';' _exp?:condition ';' _exp?:advancement ')' comment* ( block | _statement | ';' ) ) 90 | 91 | for_in_statement ::= >0( 'for' '(' ( identifier | ns_qualified_name ):left 'in' ( identifier | array_ref | ns_qualified_name ):right ')' comment* ( block | _statement | ';' ) ) 92 | 93 | break_statement ::= 'break' 94 | 95 | continue_statement ::= 'continue' 96 | 97 | delete_statement ::= 'delete' ( identifier | array_ref | ns_qualified_name ) 98 | 99 | exit_statement ::= >0( 'exit' _exp? ) 100 | 101 | return_statement ::= >0( 'return' _exp? ) 102 | 103 | switch_statement ::= 'switch' '(' _exp ')' comment* switch_body 104 | 105 | switch_body ::= '{' ( switch_case | switch_default | comment )* '}' 106 | 107 | switch_case ::= >0( 'case' ( _primitive | regex ):value ':' comment* _statement? ) 108 | 109 | switch_default ::= >0( 'default' ':' comment* _statement? ) 110 | 111 | _io_statement ::= next_statement 112 | | nextfile_statement 113 | | print_statement 114 | | printf_statement 115 | | redirected_io_statement 116 | | piped_io_statement 117 | 118 | _getline_exp ::= getline_input 119 | | getline_file 120 | 121 | getline_input ::= >0( 'getline' ( identifier | ns_qualified_name | array_ref )? ) 122 | 123 | getline_file ::= 'getline' ( identifier | ns_qualified_name )? '<' _exp:filename 124 | 125 | next_statement ::= 'next' 126 | 127 | nextfile_statement ::= 'nextfile' 128 | 129 | _print_args ::= >0( _exp | exp_list ) 130 | 131 | print_statement ::= >0( 'print' ( _print_args | !( '(' ) _print_args ')' )? ) 132 | 133 | printf_statement ::= 'printf' ( _print_args | '(' _print_args ')' ) 134 | 135 | redirected_io_statement ::= >0( ( print_statement | printf_statement ) ( '>' | '>>' ) _exp:filename ) 136 | 137 | piped_io_statement ::= >0( ( print_statement | printf_statement ) ( '|' | '|&' ) _exp:command ) 138 | 139 | block ::= '{' _block_content* '}' 140 | 141 | _block_content ::= <0( block | _statement | comment ) 142 | 143 | _exp ::= identifier 144 | | ns_qualified_name 145 | | ternary_exp 146 | | binary_exp 147 | | unary_exp 148 | | update_exp 149 | | assignment_exp 150 | | field_ref 151 | | func_call 152 | | indirect_func_call 153 | | _primitive 154 | | array_ref 155 | | regex 156 | | regex_constant 157 | | grouping 158 | | piped_io_exp 159 | | string_concat 160 | | _getline_exp 161 | 162 | ternary_exp ::= >0( _exp:condition '?' comment? _exp:consequence ':' comment? _exp:alternative ) 163 | 164 | binary_exp ::= ':operator _exp:right ) 173 | | =':operator _exp:right ) 175 | | 0( ( identifier | array_ref | field_ref | ns_qualified_name ):left ( '=' | '+=' | '-=' | '*=' | '/=' | '%=' | '^=' ) _exp:right ) 192 | 193 | piped_io_exp ::= _exp:command ( '|' | '|&' ) getline_input 194 | 195 | string_concat ::= <0( ( identifier | ns_qualified_name | ternary_exp | binary_exp | unary_exp | field_ref | func_call | _primitive | array_ref | grouping | string_concat ):left concatenating_space ( identifier | ns_qualified_name | ternary_exp | binary_exp | unary_exp | field_ref | func_call | _primitive | array_ref | grouping | string_concat ):right ) 196 | 197 | field_ref ::= '$' _exp 198 | 199 | array_ref ::= ( identifier | array_ref | ns_qualified_name ) '[' ( _exp | exp_list ):index ']' 200 | 201 | exp_list ::= ( _exp ',' )+ _exp 202 | 203 | regex ::= '/' ( regex_pattern:pattern )? !( '/' ) ( regex_flags:flags )? 204 | 205 | _regex_char ::= !( /[^/\\\[\n\r]/ ) 206 | 207 | _regex_char_escaped ::= !( '\\' /./ ) 208 | 209 | _regex_char_class ::= !( '[' ) !( ':' ) ( 'alnum' | 'alpha' | 'blank' | 'cntrl' | 'digit' | 'graph' | 'lower' | 'print' | 'punct' | 'space' | 'upper' | 'xdigit' ) !( ':' ) !( ']' ) 210 | 211 | _regex_bracket_exp ::= !( '[' ) ( _regex_char_escaped | _regex_char | _regex_char_class )+ !( ']' ) 212 | 213 | regex_pattern ::= ( _regex_char | _regex_char_escaped | _regex_bracket_exp )+ 214 | 215 | regex_flags ::= !( /[a-z]+/ ) 216 | 217 | regex_constant ::= '@' regex 218 | 219 | grouping ::= '(' _exp ')' 220 | 221 | _primitive ::= number 222 | | string 223 | 224 | identifier ::= /[a-zA-Z_][a-zA-Z0-9_]*/ 225 | 226 | namespace ::= identifier -> "namespace" 227 | 228 | ns_qualified_name ::= namespace !( '::' ) _no_space identifier 229 | 230 | number ::= /[\d.]+/ 231 | | /[\d.]+e[\d.+-]+/ 232 | 233 | string ::= '"' ( /[^"\\]+/ | escape_sequence )* '"' 234 | 235 | escape_sequence ::= !( '\\' ( '"' | /[\\abfnrtv]/ | /x[0-9a-fA-F]{1,2}/ | /[0-7]{1,3}/ ) ) 236 | 237 | func_def ::= ( 'function' | 'func' ) ( identifier | ns_qualified_name ):name '(' param_list? ')' block 238 | 239 | param_list ::= identifier ( ',' comment? identifier )* 240 | 241 | func_call ::= ( identifier | ns_qualified_name ):name !( '(' ) args? ')' 242 | 243 | indirect_func_call ::= '@' func_call 244 | 245 | args ::= _exp ( ',' _exp )* 246 | 247 | comment ::= '#' /.*/ 248 | 249 | -------------------------------------------------------------------------------- /examples/bison.ebnf: -------------------------------------------------------------------------------- 1 | ; repository: https://gitlab.com/btuin2/tree-sitter-bison 2 | ; commit: 0681f9d1d21bbccdc44ab5241426409b4313f9b5 3 | ; json from: tree-sitter-bison/src/grammar.json 4 | ; From /tmp/tslua/bison0.json 5 | ; EBNF to generate grammar.js at 6 | ; https://mingodad.github.io/lua-wasm-playground/ 7 | ; based on https://github.com/eatkins/tree-sitter-ebnf-generator 8 | ; see also https://mingodad.github.io/plgh/json2ebnf.html 9 | 10 | 11 | externals ::= { 12 | undelimited_code_block 13 | error_sentinel 14 | } 15 | 16 | extras ::= { 17 | /\s/ 18 | comment 19 | } 20 | 21 | rules: 22 | 23 | sections ::= ( prologue | declaration ';'? )* grammar_rules_section 24 | 25 | prologue ::= '%{' ( prologue_body -> embedded_code )? '%}' 26 | 27 | prologue_body ::= ( @( /([^%\n"]|%[^{}\n]|"([^"\\]|\\.)+")+/ ) )+ 28 | 29 | grammar_rules_section ::= '%%' grammar_rules_body ( '%%' epilogue )? 30 | 31 | grammar_rules_body ::= ( grammar_rule | declaration ';' )+ 32 | 33 | grammar_rule ::= grammar_rule_identifier -> grammar_rule_declaration ':' ( action? directive_empty -> directive action? | _component+ )? ( '|' ( directive_empty -> directive | _component+ ) )* ';' 34 | 35 | _component ::= ( char_literal | string_literal | grammar_rule_identifier ) ( '[' /(\p{XID_Start}|_|\\u[0-9A-Fa-f]{4}|\\U[0-9A-Fa-f]{8})(\p{XID_Continue}|\\u[0-9A-Fa-f]{4}|\\U[0-9A-Fa-f]{8})*/ ']' )? 36 | | directive_merge -> directive 37 | | action 38 | 39 | action ::= code_block 40 | 41 | declaration ::= _decl_type 42 | | _decl_require 43 | | _decl_token 44 | | _decl_nterm 45 | | _decl_op_precedence 46 | | _decl_initial_declaration 47 | | _decl_glr_parser 48 | | _decl_destructor 49 | | _decl_printer 50 | | _decl_expect 51 | | _decl_start 52 | | _decl_define 53 | | _decl_code 54 | | _decl_union 55 | | _decl_debug 56 | | _decl_header 57 | | decl_language 58 | | _decl_locations 59 | | _decl_name_prefix 60 | | _decl_no_lines 61 | | _decl_no_lines 62 | | _decl_output 63 | | _decl_pure_parser 64 | | _decl_skeleton 65 | | _decl_token_table 66 | | _decl_verbose 67 | | _decl_yacc 68 | | _decl_initial_action 69 | | _decl_parse_param 70 | | _decl_param 71 | | _decl_lex_param 72 | 73 | _decl_type ::= ( '%' !( 'type' ) ) -> declaration_name type_tag? ( grammar_rule_identifier | char_literal | string_literal )+ ( type_tag ( grammar_rule_identifier | char_literal | string_literal )+ )* 74 | 75 | _decl_require ::= ( '%' !( 'require' ) ) -> declaration_name string_literal 76 | 77 | _decl_token ::= ( '%' !( 'token' ) ) -> declaration_name type_tag? ( grammar_rule_identifier number_literal? string? )+ ( type_tag ( grammar_rule_identifier number_literal? string_literal? )+ )* 78 | 79 | _decl_nterm ::= ( '%' !( 'nterm' ) ) -> declaration_name type_tag? grammar_rule_identifier+ ( type_tag grammar_rule_identifier* )* 80 | 81 | _decl_op_precedence ::= ( '%' !( 'left' | 'right' | 'nonassoc' | 'precedence' ) ) -> declaration_name type_tag? ( ( grammar_rule_identifier | string_literal | char_literal ) number_literal? )+ ( type_tag ( ( grammar_rule_identifier | string_literal | char_literal ) number_literal? )+ )* 82 | 83 | _decl_initial_declaration ::= ( '%' !( 'initial-declaration' ) ) -> declaration_name code_block 84 | 85 | _decl_glr_parser ::= ( '%' !( 'glr-parser' ) ) -> declaration_name 86 | 87 | _decl_destructor ::= ( '%' !( 'destructor' ) ) -> declaration_name code_block ( type_tag | '<' '*'? '>' | grammar_rule_identifier )* 88 | 89 | _decl_printer ::= ( '%' !( 'printer' ) ) -> declaration_name code_block ( type_tag | '<' '*'? '>' | grammar_rule_identifier )* 90 | 91 | _decl_expect ::= ( '%' !( 'expect' | 'expect-rr' ) ) -> declaration_name @( /[0-9]+/ ) 92 | 93 | _decl_start ::= ( '%' !( 'start' ) ) -> declaration_name grammar_rule_identifier 94 | 95 | _decl_define ::= ( '%' !( 'define' ) ) -> declaration_name /(\p{XID_Start}|_|\\u[0-9A-Fa-f]{4}|\\U[0-9A-Fa-f]{8})(\p{XID_Continue}|\\u[0-9A-Fa-f]{4}|\\U[0-9A-Fa-f]{8})*/ ( '.' /(\p{XID_Start}|_|\\u[0-9A-Fa-f]{4}|\\U[0-9A-Fa-f]{8})(\p{XID_Continue}|\\u[0-9A-Fa-f]{4}|\\U[0-9A-Fa-f]{8})*/ )* ( /(\p{XID_Start}|_|\\u[0-9A-Fa-f]{4}|\\U[0-9A-Fa-f]{8})(\p{XID_Continue}|\\u[0-9A-Fa-f]{4}|\\U[0-9A-Fa-f]{8})*/ | '{' ( /(\p{XID_Start}|_|\\u[0-9A-Fa-f]{4}|\\U[0-9A-Fa-f]{8})(\p{XID_Continue}|\\u[0-9A-Fa-f]{4}|\\U[0-9A-Fa-f]{8})*/ | string_literal ) '}' | string_literal )? 96 | 97 | _decl_code ::= ( '%' !( 'code' ) ) -> declaration_name ( /(\p{XID_Start}|_|\\u[0-9A-Fa-f]{4}|\\U[0-9A-Fa-f]{8})(\p{XID_Continue}|\\u[0-9A-Fa-f]{4}|\\U[0-9A-Fa-f]{8})*/ ( '-' /(\p{XID_Start}|_|\\u[0-9A-Fa-f]{4}|\\U[0-9A-Fa-f]{8})(\p{XID_Continue}|\\u[0-9A-Fa-f]{4}|\\U[0-9A-Fa-f]{8})*/ )* )? code_block 98 | 99 | _decl_union ::= ( '%' !( 'union' ) ) -> declaration_name /(\p{XID_Start}|_|\\u[0-9A-Fa-f]{4}|\\U[0-9A-Fa-f]{8})(\p{XID_Continue}|\\u[0-9A-Fa-f]{4}|\\U[0-9A-Fa-f]{8})*/? code_block 100 | 101 | _decl_debug ::= ( '%' !( 'debug' ) ) -> declaration_name 102 | 103 | _decl_header ::= ( '%' !( 'header' ) ) -> declaration_name string_literal? 104 | 105 | decl_language ::= ( '%' !( 'language' ) ) -> declaration_name string_literal:language 106 | 107 | _decl_locations ::= ( '%' !( 'locations' ) ) -> declaration_name 108 | 109 | _decl_name_prefix ::= ( '%' !( 'name-prefix' ) ) -> declaration_name string_literal 110 | 111 | _decl_no_lines ::= ( '%' !( 'no-lines' ) ) -> declaration_name 112 | 113 | _decl_output ::= ( '%' !( 'output' ) ) -> declaration_name string_literal 114 | 115 | _decl_pure_parser ::= ( '%' !( 'pure-parser' ) ) -> declaration_name 116 | 117 | _decl_skeleton ::= ( '%' !( 'skeleton' ) ) -> declaration_name string_literal 118 | 119 | _decl_token_table ::= ( '%' !( 'token-table' ) ) -> declaration_name 120 | 121 | _decl_verbose ::= ( '%' !( 'verbose' ) ) -> declaration_name 122 | 123 | _decl_yacc ::= ( '%' !( 'yacc' ) ) -> declaration_name 124 | 125 | _decl_initial_action ::= ( '%' !( 'initial-action' ) ) -> declaration_name code_block 126 | 127 | _decl_parse_param ::= ( '%' !( 'parse-param' ) ) -> declaration_name code_block 128 | 129 | _decl_param ::= ( '%' !( 'param' ) ) -> declaration_name code_block 130 | 131 | _decl_lex_param ::= ( '%' !( 'lex-param' ) ) -> declaration_name code_block 132 | 133 | directive_merge ::= '%merge' '<' type '>' 134 | 135 | directive_empty ::= @( '%empty' ) 136 | 137 | epilogue ::= undelimited_code_block -> embedded_code 138 | 139 | string ::= string_literal 140 | | '_(' string_literal ')' 141 | 142 | string_literal ::= ( 'L"' | 'u"' | 'U"' | 'u8"' | '"' ) ( !( 1( /[^\\"\n]+/ ) ) -> string_content )* '"' 143 | 144 | number_literal ::= @( /[-\+]/? ( /0[xX]/ | /0[bB]/ )? ( ( /[0-9]/+ ( "'" /[0-9]/+ )* | /0[bB]/ /[0-9]/+ ( "'" /[0-9]/+ )* | /0[xX]/ /[0-9a-fA-F]/+ ( "'" /[0-9a-fA-F]/+ )* ) ( '.' ( /[0-9a-fA-F]/+ ( "'" /[0-9a-fA-F]/+ )* )? )? | '.' /[0-9]/+ ( "'" /[0-9]/+ )* ) ( /[eEpP]/ ( /[-\+]/? /[0-9a-fA-F]/+ ( "'" /[0-9a-fA-F]/+ )* )? )? /[uUlLwWfFbBdD]*/ ) 145 | 146 | type_tag ::= '<' type '>' 147 | 148 | type ::= _type_atom ( '<' type '>' )? 149 | 150 | _type_atom ::= /(\p{XID_Start}|_|\\u[0-9A-Fa-f]{4}|\\U[0-9A-Fa-f]{8})(\p{XID_Continue}|\\u[0-9A-Fa-f]{4}|\\U[0-9A-Fa-f]{8})*/ ( '::'? /(\p{XID_Start}|_|\\u[0-9A-Fa-f]{4}|\\U[0-9A-Fa-f]{8})(\p{XID_Continue}|\\u[0-9A-Fa-f]{4}|\\U[0-9A-Fa-f]{8})*/ )* '*'? 151 | 152 | grammar_rule_identifier ::= /(\p{XID_Start}|_|\\u[0-9A-Fa-f]{4}|\\U[0-9A-Fa-f]{8})(\p{XID_Continue}|\\u[0-9A-Fa-f]{4}|\\U[0-9A-Fa-f]{8})*/ !( !( '.' ) ( !( 'opt' ) | !( '1' ) ) ) 153 | 154 | code_block ::= '{' undelimited_code_block -> embedded_code '}' 155 | 156 | char_literal ::= "'" '\\'? /[^\n']/ "'" 157 | 158 | comment ::= '//' /.*/ 159 | | '/*' /[^*]*\*+([^/*][^*]*\*+)*/ '/' 160 | 161 | -------------------------------------------------------------------------------- /examples/cmake.ebnf: -------------------------------------------------------------------------------- 1 | ; repository: https://github.com/uyha/tree-sitter-cmake 2 | ; commit: 69d7a8b0f7493b0dbb07d54e8fea96c5421e8a71 3 | ; json from: tree-sitter-cmake/src/grammar.json 4 | ; From /tmp/tslua/cmake0.json 5 | ; EBNF to generate grammar.js at 6 | ; https://mingodad.github.io/lua-wasm-playground/ 7 | ; based on https://github.com/eatkins/tree-sitter-ebnf-generator 8 | ; see also https://mingodad.github.io/plgh/json2ebnf.html 9 | 10 | 11 | externals ::= { 12 | bracket_argument 13 | bracket_comment 14 | line_comment 15 | } 16 | 17 | rules: 18 | 19 | source_file ::= _untrimmed_command_invocation* 20 | 21 | escape_sequence ::= _escape_identity 22 | | _escape_encoded 23 | | _escape_semicolon 24 | 25 | _escape_identity ::= /\\[^A-Za-z0-9;]/ 26 | 27 | _escape_encoded ::= '\\t' 28 | | '\\r' 29 | | '\\n' 30 | 31 | _escape_semicolon ::= ';' 32 | | '\\;' 33 | 34 | variable ::= <0( ( /[a-zA-Z0-9/_.+-]/ | escape_sequence | variable_ref )+ ) 35 | 36 | variable_ref ::= normal_var 37 | | env_var 38 | | cache_var 39 | 40 | normal_var ::= '$' '{' variable '}' 41 | 42 | env_var ::= '$' 'ENV' '{' variable '}' 43 | 44 | cache_var ::= '$' 'CACHE' '{' variable '}' 45 | 46 | argument ::= bracket_argument 47 | | quoted_argument 48 | | unquoted_argument 49 | 50 | _untrimmed_argument ::= /\s/ 51 | | bracket_comment 52 | | line_comment 53 | | argument 54 | | _paren_argument 55 | 56 | _paren_argument ::= '(' _untrimmed_argument* ')' 57 | 58 | quoted_argument ::= '"' quoted_element? '"' 59 | 60 | quoted_element ::= ( variable_ref | _quoted_text | escape_sequence )+ 61 | 62 | _quoted_text ::= <0( ( '$' | /[^\\"]/ )+ ) 63 | 64 | unquoted_argument ::= >0( ( variable_ref | _unquoted_text | escape_sequence )+ ) 65 | 66 | _unquoted_text ::= <0( ( '$' | /[^()#"\\]/ )+ ) 67 | 68 | body ::= >0( _untrimmed_command_invocation+ ) 69 | 70 | argument_list ::= _untrimmed_argument+ 71 | 72 | if_command ::= if /[\t ]/* '(' argument_list ')' 73 | 74 | elseif_command ::= elseif /[\t ]/* '(' argument_list ')' 75 | 76 | else_command ::= else /[\t ]/* '(' argument_list? ')' 77 | 78 | endif_command ::= endif /[\t ]/* '(' argument_list? ')' 79 | 80 | if_condition ::= if_command ( body | elseif_command | else_command )* endif_command 81 | 82 | foreach_command ::= foreach /[\t ]/* '(' argument_list ')' 83 | 84 | endforeach_command ::= endforeach /[\t ]/* '(' argument? ')' 85 | 86 | foreach_loop ::= foreach_command body endforeach_command 87 | 88 | while_command ::= while /[\t ]/* '(' argument_list ')' 89 | 90 | endwhile_command ::= endwhile /[\t ]/* '(' ( /\s*/ argument /\s*/ )? ')' 91 | 92 | while_loop ::= while_command body endwhile_command 93 | 94 | function_command ::= function /[\t ]/* '(' argument_list ')' 95 | 96 | endfunction_command ::= endfunction /[\t ]/* '(' argument_list? ')' 97 | 98 | function_def ::= function_command body endfunction_command 99 | 100 | macro_command ::= macro /[\t ]/* '(' argument_list ')' 101 | 102 | endmacro_command ::= endmacro /[\t ]/* '(' argument_list? ')' 103 | 104 | macro_def ::= macro_command body endmacro_command 105 | 106 | block_command ::= block /[\t ]/* '(' argument_list ')' 107 | 108 | endblock_command ::= endblock /[\t ]/* '(' argument_list? ')' 109 | 110 | block_def ::= block_command body endblock_command 111 | 112 | normal_command ::= identifier /[\t ]/* '(' argument_list? ')' 113 | 114 | _command_invocation ::= normal_command 115 | | if_condition 116 | | foreach_loop 117 | | while_loop 118 | | function_def 119 | | macro_def 120 | | block_def 121 | 122 | _untrimmed_command_invocation ::= /\s/ 123 | | bracket_comment 124 | | line_comment 125 | | _command_invocation 126 | 127 | if ::= /[iI][fF]/ 128 | 129 | elseif ::= /[eE][lL][sS][eE][iI][fF]/ 130 | 131 | else ::= /[eE][lL][sS][eE]/ 132 | 133 | endif ::= /[eE][nN][dD][iI][fF]/ 134 | 135 | foreach ::= /[fF][oO][rR][eE][aA][cC][hH]/ 136 | 137 | endforeach ::= /[eE][nN][dD][fF][oO][rR][eE][aA][cC][hH]/ 138 | 139 | while ::= /[wW][hH][iI][lL][eE]/ 140 | 141 | endwhile ::= /[eE][nN][dD][wW][hH][iI][lL][eE]/ 142 | 143 | function ::= /[fF][uU][nN][cC][tT][iI][oO][nN]/ 144 | 145 | endfunction ::= /[eE][nN][dD][fF][uU][nN][cC][tT][iI][oO][nN]/ 146 | 147 | macro ::= /[mM][aA][cC][rR][oO]/ 148 | 149 | endmacro ::= /[eE][nN][dD][mM][aA][cC][rR][oO]/ 150 | 151 | block ::= /[bB][lL][oO][cC][kK]/ 152 | 153 | endblock ::= /[eE][nN][dD][bB][lL][oO][cC][kK]/ 154 | 155 | identifier ::= /[A-Za-z_][A-Za-z0-9_]*/ 156 | 157 | integer ::= /[+-]*\d+/ 158 | 159 | -------------------------------------------------------------------------------- /examples/commonlisp.ebnf: -------------------------------------------------------------------------------- 1 | ; repository: https://github.com/theHamsta/tree-sitter-commonlisp 2 | ; commit: bf2a65b1c119898a1a17389e07f2a399c05cdc0c 3 | ; json from: tree-sitter-commonlisp/src/grammar.json 4 | ; From /tmp/tslua/commonlisp0.json 5 | ; EBNF to generate grammar.js at 6 | ; https://mingodad.github.io/lua-wasm-playground/ 7 | ; based on https://github.com/eatkins/tree-sitter-ebnf-generator 8 | ; see also https://mingodad.github.io/plgh/json2ebnf.html 9 | 10 | 11 | extras ::= { 12 | block_comment 13 | } 14 | 15 | conflicts ::= { 16 | { for_clause_word package_lit } 17 | { with_clause package_lit } 18 | { with_clause } 19 | { for_clause } 20 | { accumulation_clause } 21 | } 22 | 23 | rules: 24 | 25 | source ::= ( _form | _gap )* 26 | 27 | _gap ::= _ws 28 | | comment 29 | | dis_expr 30 | 31 | _ws ::= @( /[\f\n\r\t \u000B\u001C\u001D\u001E\u001F\u2028\u2029\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2008\u2009\u200a\u205f\u3000]/+ ) 32 | 33 | comment ::= @( /(;|#!).*\n?/ ) 34 | 35 | dis_expr ::= '#_':marker _gap* _form:value 36 | 37 | _form ::= '#'? ( num_lit | fancy_literal | vec_lit | kwd_lit | ( '#':open /\d+[aA]/? list_lit ) -> vec_lit | str_lit | self_referential_reader_macro | char_lit | nil_lit | path_lit | sym_lit | package_lit | list_lit | set_lit | read_cond_lit | splicing_read_cond_lit | var_quoting_lit | quoting_lit | syn_quoting_lit | unquote_splicing_lit | unquoting_lit | include_reader_macro | complex_num_lit | '.' ) 38 | 39 | num_lit ::= @( /[+-]/? ( ( '#x' | '#X' ) /[+-]/? /[0-9a-fA-F]/+ | ( '#o' | '#O' ) /[+-]/? /[0-7]/+ | '#' /[0-9]/+ /[rR]/ /[0-9a-zA-Z]/+ | ( '#b' | '#B' ) /[+-]/? /[0-1]/+ | /[0-9]/+ '/' /[0-9]/+ | /[0-9]/+ ( '.' /[0-9]/* )? ( /[eEsSfFdDlL]/ /[+-]/? /[0-9]/+ )? | /[0-9]/+ /[MN]/? ) ) /[sSfFdDlL]/? 40 | 41 | kwd_lit ::= 4( ( ':' | '::' ) kwd_symbol ) 42 | 43 | str_lit ::= '"' ( !( 1( /[^\\~"]+/ ) ) | !( /\\./ ) | format_specifier )* '~'? '"' 44 | 45 | char_lit ::= '#' /\\([^\f\n\r\t ()]+|[()])/ 46 | 47 | nil_lit ::= @( 'nil' ) 48 | 49 | bool_lit ::= @( 'false' | 'true' ) 50 | 51 | sym_lit ::= @( /[^:\f\n\r\t ()\[\]{}"^;`\\,#'\u000B\u001C\u001D\u001E\u001F\u2028\u2029\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2008\u2009\u200a\u205f\u3000]/ ( /[^:\f\n\r\t ()\[\]{}"^;`\\,#'\u000B\u001C\u001D\u001E\u001F\u2028\u2029\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2008\u2009\u200a\u205f\u3000]/ | /[#']/ )* ) 52 | 53 | _metadata_lit ::= ( meta_lit:meta | old_meta_lit:old_meta ) _gap*? 54 | 55 | meta_lit ::= '^':marker _gap* ( read_cond_lit | map_lit | str_lit | kwd_lit | sym_lit ):value 56 | 57 | old_meta_lit ::= '#^':marker _gap* ( read_cond_lit | map_lit | str_lit | kwd_lit | sym_lit ):value 58 | 59 | list_lit ::= _metadata_lit* _bare_list_lit 60 | 61 | _bare_list_lit ::= 5( defun ) 62 | | 5( loop_macro ) 63 | | '(':open ( _form:value | _gap )* ')':close 64 | 65 | map_lit ::= _metadata_lit* _bare_map_lit 66 | 67 | _bare_map_lit ::= '{':open ( _form:value | _gap )* '}':close 68 | 69 | vec_lit ::= 5( ( '#0A' | '#0a' ):open ( num_lit | complex_num_lit ) | '#':open array_dimension? list_lit ) 70 | 71 | _bare_vec_lit ::= '[':open ( _form:value | _gap )* ']':close 72 | 73 | set_lit ::= _metadata_lit* _bare_set_lit 74 | 75 | _bare_set_lit ::= '#':marker '{':open ( _form:value | _gap )* '}':close 76 | 77 | anon_fn_lit ::= _metadata_lit* '#':marker _bare_list_lit 78 | 79 | regex_lit ::= '#':marker @( '"' /[^"\\]/* ( '\\' /./ /[^"\\]/* )* '"' ) 80 | 81 | read_cond_lit ::= _metadata_lit* '#?':marker _ws* _bare_list_lit 82 | 83 | splicing_read_cond_lit ::= _metadata_lit* '#?@':marker _ws* _bare_list_lit 84 | 85 | auto_res_mark ::= @( '::' ) 86 | 87 | ns_map_lit ::= _metadata_lit* '#':marker ( auto_res_mark | kwd_lit ):prefix _gap* _bare_map_lit 88 | 89 | var_quoting_lit ::= _metadata_lit* "#'":marker _gap* _form:value 90 | 91 | sym_val_lit ::= '##':marker _gap* sym_lit:value 92 | 93 | evaling_lit ::= _metadata_lit* '#=':marker _gap* ( list_lit | read_cond_lit | sym_lit ):value 94 | 95 | tagged_or_ctor_lit ::= _metadata_lit* '#':marker _gap* sym_lit:tag _gap* _form:value 96 | 97 | derefing_lit ::= _metadata_lit* '@':marker _gap* _form:value 98 | 99 | quoting_lit ::= _metadata_lit* "'":marker _gap* _form:value 100 | 101 | syn_quoting_lit ::= '`':marker _gap* _form:value 102 | 103 | unquote_splicing_lit ::= _metadata_lit* ',@':marker _gap* _form:value 104 | 105 | unquoting_lit ::= ',':marker _gap* _form:value 106 | 107 | block_comment ::= @( '#|' ( /[^|]/ | /\|[^#]/ )* '|#' ) 108 | 109 | fancy_literal ::= @( '|' /[^|]/* '|' ) 110 | 111 | defun ::= 5( '(':open _gap? defun_header _gap? ( _form:value | _gap )* ')':close ) 112 | 113 | _format_token ::= @( /[+-]/? ( ( '#x' | '#X' ) /[+-]/? /[0-9a-fA-F]/+ | ( '#o' | '#O' ) /[+-]/? /[0-7]/+ | '#' /[0-9]/+ /[rR]/ /[0-9a-zA-Z]/+ | ( '#b' | '#B' ) /[+-]/? /[0-1]/+ | /[0-9]/+ '/' /[0-9]/+ | /[0-9]/+ ( '.' /[0-9]/* )? ( /[eEsSfFdDlL]/ /[+-]/? /[0-9]/+ )? | /[0-9]/+ /[MN]/? ) ) -> num_lit 114 | | "'" /./ -> char_lit 115 | 116 | format_prefix_parameters ::= 'v' 117 | | 'V' 118 | | '#' 119 | 120 | format_modifiers ::= ( _format_token | ',' )* ( '@' | '@:' | ':' | ':@' ) 121 | 122 | format_directive_type ::= ( _format_token:repetitions )? ( '~' | '%' | '&' | '|' ) 123 | | /[cC]/ 124 | | /\^/ 125 | | '\n' 126 | | '\r' 127 | | /[pP]/ 128 | | /[iI]/ 129 | | /[wW]/ 130 | | /[aA]/ 131 | | '_' 132 | | /[()]/ 133 | | /[{}]/ 134 | | /[\[\]]/ 135 | | /[<>]/ 136 | | ';' 137 | | _format_token:numberOfArgs '*' 138 | | '/' ( _package_lit_without_slash -> package_lit | _sym_lit_without_slash ) '/' 139 | | '?' 140 | | 'Newline' 141 | | ( _format_token | ',' )* /[$rRbBdDgGxXeEoOsStTfF]/ 142 | 143 | format_specifier ::= <0( '~' format_prefix_parameters? format_modifiers? 5( format_directive_type ) ) 144 | 145 | for_clause_word ::= ( 'cl'? ':' )? ( 'in' | 'across' | 'being' | 'using' | /being (the|each) (hash-key[s]?|hash-value[s]?|present-symbol[s]?) (in|of)/ | 'below' | 'above' | 'from' | 'to' | 'upto' | 'upfrom' | 'downto' | 'downfrom' | 'on' | 'by' | 'then' | '=' ) 146 | 147 | _for_part ::= _gap* for_clause_word _gap* _form 148 | 149 | accumulation_verb ::= ( 'cl'? ':' )? /(maximize|minimize|(collect|append|nconc|count)(ing)?|sum(ming)?|maximizing|minimizing)/ 150 | 151 | for_clause ::= ( ( 'cl'? ':' )? 'for' | ( 'cl'? ':' )? 'and' | ( 'cl'? ':' )? 'as' ) _gap* _form:variable ( ( _gap* _form ):type )? _for_part+ 152 | | ( 'cl'? ':' )? 'and' 153 | 154 | with_clause ::= ( 'cl'? ':' )? 'with' _gap* ( _form | _form _gap* _form:type ) _gap* ( ( 'cl'? ':' )? '=' _gap* )? ( _form _gap* )? 155 | 156 | do_clause ::= <0( ( 'cl'? ':' )? 'do' <0( _gap* _form _gap* ) + ) 157 | 158 | while_clause ::= <0( ( ( 'cl'? ':' )? 'while' | ( 'cl'? ':' )? 'until' ) _gap* _form ) 159 | 160 | repeat_clause ::= <0( ( 'cl'? ':' )? 'repeat' _gap* _form ) 161 | 162 | condition_clause ::= <0( ( ( 'cl'? ':' )? 'when' | ( 'cl'? ':' )? 'if' | ( 'cl'? ':' )? 'unless' | ( 'cl'? ':' )? 'always' | ( 'cl'? ':' )? 'thereis' | ( 'cl'? ':' )? 'never' ) _gap* _form | ( 'cl'? ':' )? 'else' ) 163 | 164 | accumulation_clause ::= accumulation_verb _gap* _form ( _gap* ( 'cl'? ':' )? 'into' _gap* _form )? 165 | 166 | termination_clause ::= <0( ( ( 'cl'? ':' )? 'finally' | ( 'cl'? ':' )? 'return' | ( 'cl'? ':' )? 'initially' ) _gap* _form ) 167 | 168 | loop_clause ::= ( for_clause | do_clause | list_lit | while_clause | repeat_clause | accumulation_clause | condition_clause | with_clause | termination_clause | while_clause ) 169 | 170 | loop_macro ::= 5( '(':open _gap? ( 'cl' ':' )? 'loop' ( loop_clause | _gap )* ')':close ) 171 | 172 | defun_keyword ::= 10( ( 'cl' ':' )? ( 'defun' | 'defmacro' | 'defgeneric' | 'defmethod' ) ) 173 | 174 | defun_header ::= 5( defun_keyword:keyword _gap* ( unquoting_lit | unquote_splicing_lit ) | defun_keyword:keyword _gap* _form:function_name ( ( _gap* ( kwd_lit | sym_lit ) ):specifier )? _gap* ( list_lit | unquoting_lit ):lambda_list | ( 'lambda' -> defun_keyword ):keyword _gap* ( list_lit | unquoting_lit ):lambda_list ) 175 | 176 | array_dimension ::= 100( /\d+[aA]/ ) 177 | 178 | path_lit ::= 5( ( '#P' | '#p' ):open @( '"' /[^"\\]/* ( '\\' /./ /[^"\\]/* )* '"' ) -> str_lit ) 179 | 180 | package_lit ::= 2( ( sym_lit | 'cl' ):package ( ':' | '::' ) sym_lit:symbol | 1( 'cl' ) ) 181 | 182 | _package_lit_without_slash ::= ( _sym_lit_without_slash | 'cl' ):package ( ':' | '::' ) _sym_lit_without_slash:symbol 183 | 184 | _sym_lit_without_slash ::= /[^:\f\n\r\t ()\[\]{}"^;/`\\,#'\u000B\u001C\u001D\u001E\u001F\u2028\u2029\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2008\u2009\u200a\u205f\u3000]/+ -> sym_lit 185 | 186 | kwd_symbol ::= @( /[^:\f\n\r\t ()\[\]{}"^;`\\,#'\u000B\u001C\u001D\u001E\u001F\u2028\u2029\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2008\u2009\u200a\u205f\u3000]/ ( /[^:\f\n\r\t ()\[\]{}"^;`\\,#'\u000B\u001C\u001D\u001E\u001F\u2028\u2029\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2008\u2009\u200a\u205f\u3000]/ | /[#']/ )* ) 187 | 188 | self_referential_reader_macro ::= /#\d+[=#]/ 189 | 190 | include_reader_macro ::= _metadata_lit* ( '#+' | '#-' ):marker _gap* _form:condition _gap* _form:target 191 | 192 | complex_num_lit ::= _metadata_lit* ( '#C' | '#c' ):marker _gap* '(' _gap* num_lit:real _gap* num_lit:imaginary _gap* ')' 193 | 194 | -------------------------------------------------------------------------------- /examples/css.ebnf: -------------------------------------------------------------------------------- 1 | ; repository: https://github.com/tree-sitter/tree-sitter-css.git 2 | ; commit: a68fcd1e6b03118d1e92ffa45e7ab7a39d52d3f7 3 | ; json from: tree-sitter-css/src/grammar.json 4 | ; From /tmp/tslua/css0.json 5 | ; EBNF to generate grammar.js at 6 | ; https://mingodad.github.io/lua-wasm-playground/ 7 | ; based on https://github.com/eatkins/tree-sitter-ebnf-generator 8 | ; see also https://mingodad.github.io/plgh/json2ebnf.html 9 | 10 | 11 | externals ::= { 12 | _descendant_operator 13 | _pseudo_class_selector_colon 14 | __error_recovery 15 | } 16 | 17 | extras ::= { 18 | /\s/ 19 | comment 20 | js_comment 21 | } 22 | 23 | inline ::= { 24 | _top_level_item 25 | _block_item 26 | } 27 | 28 | rules: 29 | 30 | stylesheet ::= _top_level_item* 31 | 32 | _top_level_item ::= declaration 33 | | rule_set 34 | | import_statement 35 | | media_statement 36 | | charset_statement 37 | | namespace_statement 38 | | keyframes_statement 39 | | supports_statement 40 | | at_rule 41 | 42 | import_statement ::= '@import' _value ( _query ( ',' _query )* )? ';' 43 | 44 | media_statement ::= '@media' _query ( ',' _query )* block 45 | 46 | charset_statement ::= '@charset' _value ';' 47 | 48 | namespace_statement ::= '@namespace' ( identifier -> namespace_name )? ( string_value | call_expression ) ';' 49 | 50 | keyframes_statement ::= ( '@keyframes' | /@[-a-z]+keyframes/ -> at_keyword ) identifier -> keyframes_name keyframe_block_list 51 | 52 | keyframe_block_list ::= '{' keyframe_block* '}' 53 | 54 | keyframe_block ::= ( from | to | integer_value ) block 55 | 56 | from ::= 'from' 57 | 58 | to ::= 'to' 59 | 60 | supports_statement ::= '@supports' _query block 61 | 62 | postcss_statement ::= -1( at_keyword _value* ';' ) 63 | 64 | at_rule ::= at_keyword ( _query ( ',' _query )* )? ( ';' | block ) 65 | 66 | rule_set ::= selectors block 67 | 68 | selectors ::= _selector ( ',' _selector )* 69 | 70 | block ::= '{' _block_item* ( last_declaration -> declaration )? '}' 71 | 72 | _block_item ::= declaration 73 | | rule_set 74 | | import_statement 75 | | media_statement 76 | | charset_statement 77 | | namespace_statement 78 | | keyframes_statement 79 | | supports_statement 80 | | postcss_statement 81 | | at_rule 82 | 83 | _selector ::= universal_selector 84 | | identifier -> tag_name 85 | | class_selector 86 | | nesting_selector 87 | | pseudo_class_selector 88 | | pseudo_element_selector 89 | | id_selector 90 | | attribute_selector 91 | | string_value 92 | | child_selector 93 | | descendant_selector 94 | | sibling_selector 95 | | adjacent_sibling_selector 96 | | namespace_selector 97 | 98 | nesting_selector ::= '&' 99 | 100 | universal_selector ::= '*' 101 | 102 | class_selector ::= 1( _selector? '.' identifier -> class_name ) 103 | 104 | pseudo_class_selector ::= _selector? _pseudo_class_selector_colon -> ":" ( ( 'has' | 'not' | 'is' | 'where' ) -> class_name pseudo_class_with_selector_arguments -> arguments | identifier -> class_name ( pseudo_class_arguments -> arguments )? ) 105 | 106 | pseudo_element_selector ::= _selector? '::' identifier -> tag_name ( pseudo_element_arguments -> arguments )? 107 | 108 | id_selector ::= _selector? '#' identifier -> id_name 109 | 110 | attribute_selector ::= _selector? '[' ( identifier | namespace_selector ) -> attribute_name ( ( '=' | '~=' | '^=' | '|=' | '*=' | '$=' ) _value )? ']' 111 | 112 | child_selector ::= <0( _selector '>' _selector ) 113 | 114 | descendant_selector ::= <0( _selector _descendant_operator _selector ) 115 | 116 | sibling_selector ::= <0( _selector '~' _selector ) 117 | 118 | adjacent_sibling_selector ::= <0( _selector '+' _selector ) 119 | 120 | namespace_selector ::= <0( _selector '|' _selector ) 121 | 122 | pseudo_class_arguments ::= !( '(' ) ( ( _selector | _value+ ) ( ',' ( _selector | _value+ ) )* )? ')' 123 | 124 | pseudo_class_with_selector_arguments ::= !( '(' ) ( _selector ( ',' _selector )* )? ')' 125 | 126 | pseudo_element_arguments ::= !( '(' ) ( ( _selector | _value+ ) ( ',' ( _selector | _value+ ) )* )? ')' 127 | 128 | declaration ::= identifier -> property_name ':' _value ( ','? _value )* important? ';' 129 | 130 | last_declaration ::= 1( identifier -> property_name ':' _value ( ','? _value )* important? ) 131 | 132 | important ::= '!important' 133 | 134 | _query ::= identifier -> keyword_query 135 | | feature_query 136 | | binary_query 137 | | unary_query 138 | | selector_query 139 | | parenthesized_query 140 | 141 | feature_query ::= '(' identifier -> feature_name ':' _value+ ')' 142 | 143 | parenthesized_query ::= '(' _query ')' 144 | 145 | binary_query ::= <0( _query ( 'and' | 'or' ) _query ) 146 | 147 | unary_query ::= 1( ( 'not' | 'only' ) _query ) 148 | 149 | selector_query ::= 'selector' '(' _selector ')' 150 | 151 | _value ::= -1( identifier -> plain_value | plain_value | color_value | integer_value | float_value | string_value | grid_value | binary_expression | parenthesized_value | call_expression | important ) 152 | 153 | parenthesized_value ::= '(' _value ')' 154 | 155 | color_value ::= '#' !( /[0-9a-fA-F]{3,8}/ ) 156 | 157 | string_value ::= "'" /([^'\n]|\\(.|\n))*/ "'" 158 | | '"' /([^"\n]|\\(.|\n))*/ '"' 159 | 160 | integer_value ::= @( ( '+' | '-' )? /\d+/ ) unit? 161 | 162 | float_value ::= @( ( '+' | '-' )? /\d*/ ( '.' /\d+/ | /[eE]/ '-'? /\d+/ | '.' /\d+/ /[eE]/ '-'? /\d+/ ) ) unit? 163 | 164 | unit ::= !( /[a-zA-Z%]+/ ) 165 | 166 | grid_value ::= '[' _value ( ',' _value )* ']' 167 | 168 | call_expression ::= identifier -> function_name arguments 169 | 170 | binary_expression ::= <0( _value ( '+' | '-' | '*' | '/' ) _value ) 171 | 172 | arguments ::= !( '(' ) ( _value+ ( ( ',' | ';' ) _value+ )* )? ')' 173 | 174 | identifier ::= /(--|-?[a-zA-Z_\xA0-\xFF])[a-zA-Z0-9-_\xA0-\xFF]*/ 175 | 176 | at_keyword ::= /@[a-zA-Z-_]+/ 177 | 178 | js_comment ::= @( -1( '//' /.*/ ) ) 179 | 180 | comment ::= @( '/*' /[^*]*\*+([^/*][^*]*\*+)*/ '/' ) 181 | 182 | plain_value ::= @( ( /[-_]/ | /\/[^\*\s,;!{}()\[\]]/ )* /[a-zA-Z]/ ( /[^/\s,;!{}()\[\]]/ | /\/[^\*\s,;!{}()\[\]]/ )* ) 183 | 184 | -------------------------------------------------------------------------------- /examples/cvt-tree-sitter-grammars.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | mycw=$PWD 3 | tmp_folder="/tmp/tslua" 4 | grmh="$HOME/dev/c/A_grammars" 5 | cvt_cmd="qjs $grmh/plgh/json2ebnf-lua.js" 6 | gen_cmd="qjs $grmh/plgh/tree-sitter-generate.js" 7 | base_folder="$grmh/tree-sitter" 8 | valid_cmd="qjs $mycw/schemasafe.qjs $mycw/tree-sitter-json-schema.json" 9 | fname_list="tree-sitter-ada/src/grammar.json \ 10 | tree-sitter-angular/src/grammar.json \ 11 | tree-sitter-awk/src/grammar.json \ 12 | tree-sitter-bash/src/grammar.json \ 13 | tree-sitter-bison/src/grammar.json \ 14 | tree-sitter-c/src/grammar.json \ 15 | tree-sitter-cmake/src/grammar.json \ 16 | tree-sitter-commonlisp/src/grammar.json \ 17 | tree-sitter-cpp/src/grammar.json \ 18 | tree-sitter-c-sharp/src/grammar.json \ 19 | tree-sitter-c/src/grammar.json \ 20 | tree-sitter-css/src/grammar.json \ 21 | tree-sitter-dart/src/grammar.json \ 22 | tree-sitter-dockerfile/src/grammar.json \ 23 | tree-sitter-d/src/grammar.json \ 24 | tree-sitter-elixir/src/grammar.json \ 25 | tree-sitter-elm/src/grammar.json \ 26 | tree-sitter-erlang/src/grammar.json \ 27 | tree-sitter-fortran/src/grammar.json \ 28 | tree-sitter-fsharp/fsharp/src/grammar.json \ 29 | tree-sitter-gleam/src/grammar.json \ 30 | tree-sitter-go/src/grammar.json \ 31 | tree-sitter-haskell/src/grammar.json \ 32 | tree-sitter-haxe/src/grammar.json \ 33 | tree-sitter-html/src/grammar.json \ 34 | tree-sitter-javascript/src/grammar.json \ 35 | tree-sitter-java/src/grammar.json \ 36 | tree-sitter-julia/src/grammar.json \ 37 | tree-sitter-kotlin/src/grammar.json \ 38 | tree-sitter-ld/src/grammar.json \ 39 | tree-sitter-lua/src/grammar.json \ 40 | tree-sitter-make/src/grammar.json \ 41 | tree-sitter-markdown/src/grammar.json \ 42 | tree-sitter-minizinc/src/grammar.json \ 43 | tree-sitter-nim2/src/grammar.json \ 44 | tree-sitter-ocaml/grammars/ocaml/src/grammar.json \ 45 | tree-sitter-php/php/src/grammar.json \ 46 | tree-sitter-python/src/grammar.json \ 47 | tree-sitter-regex/src/grammar.json \ 48 | tree-sitter-ruby/src/grammar.json \ 49 | tree-sitter-rust/src/grammar.json \ 50 | tree-sitter-scala/src/grammar.json \ 51 | tree-sitter-sql/src/grammar.json \ 52 | tree-sitter-squirrel/src/grammar.json \ 53 | tree-sitter-swift/src/grammar.json \ 54 | tree-sitter-teal/src/grammar.json \ 55 | tree-sitter-tlaplus/src/grammar.json \ 56 | tree-sitter-typescript/typescript/src/grammar.json \ 57 | tree-sitter-vim/src/grammar.json \ 58 | tree-sitter-vimdoc/src/grammar.json \ 59 | tree-sitter-zig/src/grammar.json" 60 | 61 | #fname_list="tree-sitter-make/src/grammar.json" 62 | #"v-analyzer/tree_sitter_v/src/grammar.json" 63 | 64 | if [ ! -d $tmp_folder ]; then 65 | mkdir $tmp_folder 66 | fi 67 | 68 | for fn in $fname_list 69 | do 70 | echo $fn 71 | fn_basename=`echo $fn | sed -E -e 's/tree-sitter-([^/]+)\/.+/\1/'` 72 | echo $fn_basename 73 | 74 | repo_base=`echo $fn | sed -E -e 's/(tree-sitter-[^/]+)\/.+/\1/'` 75 | repo_base="$base_folder/$repo_base" 76 | echo $repo_base 77 | cd $repo_base 78 | repo_url=`git config --get remote.origin.url` 79 | echo $repo_url 80 | repo_last_commit=`git rev-parse HEAD` 81 | echo $repo_last_commit 82 | cd $mycw 83 | 84 | tmp_fn_json0="$tmp_folder/${fn_basename}0.json" 85 | echo "==jsonToJson0 $tmp_fn_json0" 86 | cp $base_folder/$fn $tmp_fn_json0 87 | 88 | tmp_ebnf_fn="$tmp_folder/$fn_basename.ebnf" 89 | echo "==jsonToEbnf $tmp_ebnf_fn" 90 | echo "; repository: $repo_url" > $tmp_ebnf_fn 91 | echo "; commit: $repo_last_commit" >> $tmp_ebnf_fn 92 | echo "; json from: $fn" >> $tmp_ebnf_fn 93 | $cvt_cmd $tmp_fn_json0 >> $tmp_ebnf_fn 94 | 95 | tmp_fname_js=$tmp_folder/$fn_basename.js 96 | echo "==ebnfToJs $tmp_fname_js" 97 | lua tree-sitter-ebnf-generator-cmd.lua $tmp_ebnf_fn > $tmp_fname_js 98 | 99 | tmp_fname_json=$tmp_folder/$fn_basename.json 100 | echo "==jsToJson $tmp_fname_js" 101 | $gen_cmd $tmp_fname_js > $tmp_fname_json 102 | 103 | $valid_cmd $tmp_fname_json 104 | $valid_cmd $tmp_fn_json0 105 | done 106 | -------------------------------------------------------------------------------- /examples/dockerfile.ebnf: -------------------------------------------------------------------------------- 1 | ; repository: https://github.com/camdencheek/tree-sitter-dockerfile.git 2 | ; commit: 087daa20438a6cc01fa5e6fe6906d77c869d19fe 3 | ; json from: tree-sitter-dockerfile/src/grammar.json 4 | ; From /tmp/tslua/dockerfile0.json 5 | ; EBNF to generate grammar.js at 6 | ; https://mingodad.github.io/lua-wasm-playground/ 7 | ; based on https://github.com/eatkins/tree-sitter-ebnf-generator 8 | ; see also https://mingodad.github.io/plgh/json2ebnf.html 9 | 10 | 11 | externals ::= { 12 | heredoc_marker 13 | heredoc_line 14 | heredoc_end 15 | heredoc_nl 16 | error_sentinel 17 | } 18 | 19 | extras ::= { 20 | /\s+/ 21 | line_continuation 22 | comment 23 | } 24 | 25 | rules: 26 | 27 | source_file ::= ( _instruction '\n' )* 28 | 29 | _instruction ::= from_instruction 30 | | run_instruction 31 | | cmd_instruction 32 | | label_instruction 33 | | expose_instruction 34 | | env_instruction 35 | | add_instruction 36 | | copy_instruction 37 | | entrypoint_instruction 38 | | volume_instruction 39 | | user_instruction 40 | | workdir_instruction 41 | | arg_instruction 42 | | onbuild_instruction 43 | | stopsignal_instruction 44 | | healthcheck_instruction 45 | | shell_instruction 46 | | maintainer_instruction 47 | | cross_build_instruction 48 | 49 | from_instruction ::= /[fF][rR][oO][mM]/ -> "FROM" param? image_spec ( /[aA][sS]/ -> "AS" image_alias:as )? 50 | 51 | run_instruction ::= /[rR][uU][nN]/ -> "RUN" ( param | mount_param )* ( json_string_array | shell_command ) heredoc_block* 52 | 53 | cmd_instruction ::= /[cC][mM][dD]/ -> "CMD" ( json_string_array | shell_command ) 54 | 55 | label_instruction ::= /[lL][aA][bB][eE][lL]/ -> "LABEL" label_pair+ 56 | 57 | expose_instruction ::= /[eE][xX][pP][oO][sS][eE]/ -> "EXPOSE" ( expose_port | expansion )+ 58 | 59 | env_instruction ::= /[eE][nN][vV]/ -> "ENV" ( env_pair+ | _spaced_env_pair -> env_pair ) 60 | 61 | add_instruction ::= /[aA][dD][dD]/ -> "ADD" param* ( path_with_heredoc -> path _non_newline_whitespace )+ path_with_heredoc -> path heredoc_block* 62 | 63 | copy_instruction ::= /[cC][oO][pP][yY]/ -> "COPY" param* ( path_with_heredoc -> path _non_newline_whitespace )+ path_with_heredoc -> path heredoc_block* 64 | 65 | entrypoint_instruction ::= /[eE][nN][tT][rR][yY][pP][oO][iI][nN][tT]/ -> "ENTRYPOINT" ( json_string_array | shell_command ) 66 | 67 | volume_instruction ::= /[vV][oO][lL][uU][mM][eE]/ -> "VOLUME" ( json_string_array | path ( _non_newline_whitespace path )* ) 68 | 69 | user_instruction ::= /[uU][sS][eE][rR]/ -> "USER" ( _user_name_or_group -> unquoted_string ):user ( !( ':' ) ( _immediate_user_name_or_group -> unquoted_string ):group )? 70 | 71 | _user_name_or_group ::= ( /([a-zA-Z][-A-Za-z0-9_]*|[0-9]+)/ | expansion ) _immediate_user_name_or_group_fragment* 72 | 73 | _immediate_user_name_or_group ::= _immediate_user_name_or_group_fragment+ 74 | 75 | _immediate_user_name_or_group_fragment ::= !( /([a-zA-Z][-a-zA-Z0-9_]*|[0-9]+)/ ) 76 | | _immediate_expansion 77 | 78 | workdir_instruction ::= /[wW][oO][rR][kK][dD][iI][rR]/ -> "WORKDIR" path 79 | 80 | arg_instruction ::= /[aA][rR][gG]/ -> "ARG" ( /[a-zA-Z0-9_]+/ -> unquoted_string ):name ( !( '=' ) ( double_quoted_string | single_quoted_string | unquoted_string ):default )? 81 | 82 | onbuild_instruction ::= /[oO][nN][bB][uU][iI][lL][dD]/ -> "ONBUILD" _instruction 83 | 84 | stopsignal_instruction ::= /[sS][tT][oO][pP][sS][iI][gG][nN][aA][lL]/ -> "STOPSIGNAL" _stopsignal_value 85 | 86 | _stopsignal_value ::= ( /[A-Z0-9]+/ | expansion ) ( !( /[A-Z0-9]+/ ) | _immediate_expansion )* 87 | 88 | healthcheck_instruction ::= /[hH][eE][aA][lL][tT][hH][cC][hH][eE][cC][kK]/ -> "HEALTHCHECK" ( 'NONE' | param* cmd_instruction ) 89 | 90 | shell_instruction ::= /[sS][hH][eE][lL][lL]/ -> "SHELL" json_string_array 91 | 92 | maintainer_instruction ::= /[mM][aA][iI][nN][tT][aA][iI][nN][eE][rR]/ -> "MAINTAINER" /.*/ 93 | 94 | cross_build_instruction ::= /[cC][rR][oO][sS][sS]_[bB][uU][iI][lL][dD][a-zA-Z_]*/ -> "CROSS_BUILD" /.*/ 95 | 96 | heredoc_block ::= heredoc_nl -> "_heredoc_nl" ( heredoc_line '\n' )* heredoc_end 97 | 98 | path ::= ( /[^-\s\$<]/ | /<[^<]/ | expansion ) ( !( /[^\s\$]+/ ) | _immediate_expansion )* 99 | 100 | path_with_heredoc ::= heredoc_marker 101 | | ( /[^-\s\$<]/ | /<[^-\s\$<]/ | expansion ) ( !( /[^\s\$]+/ ) | _immediate_expansion )* 102 | 103 | expansion ::= '$' _expansion_body 104 | 105 | _immediate_expansion ::= _imm_expansion -> expansion 106 | 107 | _imm_expansion ::= !( '$' ) _expansion_body 108 | 109 | _expansion_body ::= variable 110 | | !( '{' ) !( /[^\}]+/ ) -> variable !( '}' ) 111 | 112 | variable ::= !( /[a-zA-Z_][a-zA-Z0-9_]*/ ) 113 | 114 | env_pair ::= _env_key:name !( '=' ) ( ( double_quoted_string | single_quoted_string | unquoted_string ):value )? 115 | 116 | _spaced_env_pair ::= _env_key:name !( /\s+/ ) ( double_quoted_string | single_quoted_string | unquoted_string ):value 117 | 118 | _env_key ::= /[a-zA-Z_][a-zA-Z0-9_]*/ -> unquoted_string 119 | 120 | expose_port ::= /\d+(-\d+)?/ ( '/tcp' | '/udp' )? 121 | 122 | label_pair ::= ( /[-a-zA-Z0-9\._]+/ -> unquoted_string | double_quoted_string | single_quoted_string ):key !( '=' ) ( double_quoted_string | single_quoted_string | unquoted_string ):value 123 | 124 | image_spec ::= image_name:name image_tag?:tag image_digest?:digest 125 | 126 | image_name ::= ( /[^@:\s\$-]/ | expansion ) ( !( /[^@:\s\$]+/ ) | _immediate_expansion )* 127 | 128 | image_tag ::= !( ':' ) ( !( /[^@\s\$]+/ ) | _immediate_expansion )+ 129 | 130 | image_digest ::= !( '@' ) ( !( /[a-zA-Z0-9:]+/ ) | _immediate_expansion )+ 131 | 132 | param ::= '--' !( /[a-z][-a-z]*/ ):name !( '=' ) !( /[^\s]+/ ):value 133 | 134 | mount_param ::= '--' !( 'mount' ):name !( '=' ) ( mount_param_param ( !( ',' ) mount_param_param )* ):value 135 | 136 | mount_param_param ::= !( /[^\s=,]+/ ) !( '=' ) !( /[^\s=,]+/ ) 137 | 138 | image_alias ::= ( /[-a-zA-Z0-9_]+/ | expansion ) ( !( /[-a-zA-Z0-9_]+/ ) | _immediate_expansion )* 139 | 140 | shell_command ::= shell_fragment ( required_line_continuation -> line_continuation shell_fragment )* 141 | 142 | shell_fragment ::= ( heredoc_marker /[ \t]*/ | /[,=-]/ | /[^\\\[\n#\s,=-][^\\\n<]*/ | /\\[^\n,=-]/ | /<[^<]/ )+ 143 | 144 | line_continuation ::= /\\[ \t]*\n/ 145 | 146 | required_line_continuation ::= '\\\n' 147 | 148 | json_string_array ::= '[' ( json_string ( ',' json_string )* )? ']' 149 | 150 | json_string ::= '"' ( !( /[^"\\]+/ ) | json_escape_sequence -> escape_sequence )* '"' 151 | 152 | json_escape_sequence ::= !( /\\(?:["\\/bfnrt]|u[0-9A-Fa-f]{4})/ ) 153 | 154 | double_quoted_string ::= '"' ( !( /[^"\n\\\$]+/ ) | double_quoted_escape_sequence -> escape_sequence | '\\' | _immediate_expansion )* '"' 155 | 156 | single_quoted_string ::= "'" ( !( /[^'\n\\]+/ ) | single_quoted_escape_sequence -> escape_sequence | '\\' )* "'" 157 | 158 | unquoted_string ::= ( !( /[^\s\n\"'\\\$]+/ ) | !( '\\ ' ) | _immediate_expansion )+ 159 | 160 | double_quoted_escape_sequence ::= !( '\\\\' | '\\"' ) 161 | 162 | single_quoted_escape_sequence ::= !( '\\\\' | "\\'" ) 163 | 164 | _non_newline_whitespace ::= !( /[\t ]+/ ) 165 | 166 | comment ::= /#.*/ 167 | 168 | -------------------------------------------------------------------------------- /examples/erlang.ebnf: -------------------------------------------------------------------------------- 1 | ; repository: https://github.com/AbstractMachinesLab/tree-sitter-erlang.git 2 | ; commit: 3a9c769444f08bbccce03845270efac0c641c5e7 3 | ; json from: tree-sitter-erlang/src/grammar.json 4 | ; From /tmp/tslua/erlang0.json 5 | ; EBNF to generate grammar.js at 6 | ; https://mingodad.github.io/lua-wasm-playground/ 7 | ; based on https://github.com/eatkins/tree-sitter-ebnf-generator 8 | ; see also https://mingodad.github.io/plgh/json2ebnf.html 9 | 10 | 11 | extras ::= { 12 | /[\x01-\x20\x80-\xA0]/ 13 | comment 14 | } 15 | 16 | inline ::= { 17 | term 18 | expression 19 | } 20 | 21 | conflicts ::= { 22 | { _structure_item _expr_operator_binary } 23 | { _structure_item expr_map_update expr_record_access expr_record_update } 24 | } 25 | 26 | word ::= _unquoted_atom 27 | 28 | rules: 29 | 30 | source_file ::= _structure_item* 31 | 32 | _structure_item ::= 100( expression ) 33 | | 8( _module ) 34 | 35 | _module ::= type_declaration 36 | | function_spec 37 | | function_declaration 38 | | module_attribute 39 | | module_name 40 | | module_export 41 | 42 | module_attribute ::= '-' atom '(' expression ')' '.' 43 | 44 | module_name ::= '-' 'module' '(' atom ')' '.' 45 | 46 | module_export ::= '-' ( 'export' | 'export_type' ) '(' '[' ( atom '/' integer ( ',' atom '/' integer )* )? ']' ')' '.' 47 | 48 | function_declaration ::= function_clause ( ';' function_clause )* '.' 49 | 50 | function_clause ::= 7( atom:name lambda_clause ) 51 | 52 | comment ::= /%.*/ 53 | 54 | type_declaration ::= '-' ( 'type' | 'opaque' ) atom:name ( '(' ( variable ( ',' variable )* )? ')' ):arguments '::' type_expression:def '.' 55 | 56 | function_spec ::= '-' ( 'spec' | 'callback' ) atom:name ( '(' ( type_expression ( ',' type_expression )* )? ')' ):arguments '->' type_expression:def '.' 57 | 58 | type_expression ::= ( type_atom | type_application | type_bitstring | type_fun | type_integer | type_map | type_record | type_tuple | type_variable | _type_list ) ( '|' ( type_atom | type_application | type_bitstring | type_fun | type_integer | type_map | type_record | type_tuple | type_variable | _type_list ) )* 59 | 60 | type_variable ::= variable 61 | 62 | type_atom ::= atom 63 | 64 | type_application ::= >1( ( atom ':' )? atom ( '(' ( type_expression ( ',' type_expression )* )? ')' ):arguments ) 65 | 66 | type_bitstring ::= '<<' ( '_' ':' variable | '_' ':' '_' '*' variable | '_' ':' variable '_' ':' '_' '*' variable | '>>' ) 67 | 68 | type_fun ::= 'fun' '(' ( '(' '...' ')' '->' type_expression | ( '(' ( type_expression ( ',' type_expression )* )? ')' ):arguments '->' type_expression )? ')' 69 | 70 | type_integer ::= integer 71 | | integer '..' integer 72 | 73 | _type_list ::= type_list 74 | | type_nonempty_list 75 | 76 | type_list ::= '[' type_expression ']' 77 | 78 | type_nonempty_list ::= '[' type_expression ',' '...' ']' 79 | 80 | type_tuple ::= '{' ( type_expression ( ',' type_expression )* )? '}' 81 | 82 | type_map ::= '#' '{' ( type_map_entry ( ',' type_map_entry )* )? '}' 83 | 84 | type_map_entry ::= type_expression ( '=>' | ':=' ) type_expression 85 | 86 | type_record ::= '#' atom '{' ( type_record_field ( ',' type_record_field )* )? '}' 87 | 88 | type_record_field ::= type_expression '::' type_expression 89 | 90 | pattern ::= 3( term | variable | pat_list | pat_tuple ) 91 | 92 | pat_list ::= 3( '[' ( pattern ( ',' pattern )* )? ']' | pat_list_cons ) 93 | 94 | pat_list_cons ::= '[' ( pattern ( ',' pattern )* ):init '|' pattern:tail ']' 95 | 96 | pat_tuple ::= 3( '{' ( pattern ( ',' pattern )* )? '}' ) 97 | 98 | pat_map ::= '#' '{' ( pat_map_entry ( ',' pat_map_entry )* )? '}' 99 | 100 | pat_map_entry ::= term ':=' pattern 101 | 102 | expression ::= 6( '(' _expr ')' ) 103 | | 4( _expr ) 104 | 105 | _expr ::= expr_begin_block 106 | | expr_bitstring_comprehension 107 | | expr_case 108 | | expr_catch 109 | | expr_function_call 110 | | expr_if 111 | | expr_lambda 112 | | expr_list 113 | | expr_list_comprehension 114 | | expr_macro_application 115 | | expr_map_update 116 | | expr_match 117 | | expr_receive 118 | | expr_record_access 119 | | expr_record_update 120 | | expr_send 121 | | expr_throw 122 | | expr_try 123 | | expr_op 124 | | term 125 | | variable 126 | 127 | expr_map_update ::= <101( expression map ) 128 | 129 | expr_record_access ::= <101( expression '#' atom '.' atom ) 130 | 131 | expr_record_update ::= <101( expression record ) 132 | 133 | expr_try ::= 'try' expression ( 'of' case_clause ( ';' case_clause )* )? ( expr_try_catch | expr_try_after | _expr_try_catch_after ) 'end' 134 | 135 | expr_try_catch ::= 'catch' catch_clause ( ';' catch_clause )* 136 | 137 | expr_try_after ::= 'after' expression 138 | 139 | _expr_try_catch_after ::= expr_try_catch expr_try_after 140 | 141 | catch_clause ::= catch_pattern:pattern guard_clause? '->' ( expression ( ',' expression )* ):body 142 | 143 | catch_pattern ::= pattern:class ( ':' pattern )?:exception ( ':' variable )?:stacktrace 144 | 145 | expr_catch ::= <0( 'catch' expression ) 146 | 147 | expr_throw ::= <0( 'throw' expression ) 148 | 149 | expr_begin_block ::= 'begin' expression ( ',' expression )* 'end' 150 | 151 | expr_list_comprehension ::= '[' expression '||' expr_list_generator ( ',' expr_list_filter )? ']' 152 | 153 | expr_list_generator ::= expression '<-' expression 154 | 155 | expr_list_filter ::= expression ( ',' expression )* 156 | 157 | expr_bitstring_comprehension ::= '<<' term '||' expr_bitstring_generator ( ',' expr_bitstring_filter )? '>>' 158 | 159 | expr_bitstring_generator ::= '<<' expression '>>' '<=' expression 160 | 161 | expr_bitstring_filter ::= expression ( ',' expression )* 162 | 163 | expr_op ::= _expr_operator_unary 164 | | _expr_operator_binary 165 | 166 | _expr_operator_unary ::= >10( ( '+' | '-' | 'bnot' | 'not' ):operator expression:operand ) 167 | 168 | _expr_operator_binary ::= <9( expression:lhs ( '*' | '+' | '-' | '/' | '/=' | '<' | '=/=' | '=:=' | '=<' | '==' | '>' | '>=' | 'and' | 'andalso' | 'band' | 'bor' | 'bsl' | 'bsr' | 'bxor' | 'div' | 'or' | 'orelse' | 'rem' | 'xor' ):operator expression:rhs ) 169 | | >9( expression:lhs ( '=!' | '++' | '--' ):operator expression:rhs ) 170 | 171 | expr_send ::= >0( expression '!' expression ) 172 | 173 | expr_receive ::= 'receive' ( case_clause ( ';' case_clause )* )?:branches expr_receive_after? 'end' 174 | 175 | expr_receive_after ::= 'after' case_clause 176 | 177 | expr_if ::= 'if' if_clause ( ';' if_clause )* 'end' 178 | 179 | if_clause ::= guard_seq:condition '->' ( expression ( ',' expression )* ):body 180 | 181 | expr_list ::= 5( '[' ( expression ( ',' expression )* )? ']' | expr_list_cons ) 182 | 183 | expr_list_cons ::= '[' ( expression ( ',' expression )* ):init '|' expression:tail ']' 184 | 185 | expr_case ::= 'case' expression 'of' case_clause ( ';' case_clause )* 'end' 186 | 187 | case_clause ::= pattern:pattern guard_clause? '->' ( expression ( ',' expression )* ):body 188 | 189 | guard_clause ::= 'when' guard_seq 190 | 191 | guard_seq ::= guard ( ';' guard )* 192 | 193 | guard ::= expression ( ',' expression )* 194 | 195 | expr_match ::= >-1( expression '=' expression ) 196 | 197 | expr_lambda ::= 'fun' lambda_clause ( ';' lambda_clause )* 'end' 198 | 199 | lambda_clause ::= ( ( '(' ( pattern ( ',' pattern )* )? ')' ):arguments ):arguments guard_clause? '->' ( expression ( ',' expression )* ):body 200 | 201 | expr_function_call ::= _function_name:name ( '(' ( expression ( ',' expression )* )? ')' ):arguments 202 | 203 | _function_name ::= 5( computed_function_name | qualified_function_name ) 204 | 205 | qualified_function_name ::= ( variable | atom | '(' expression ')' ):module_name ':' ( variable | atom | '(' expression ')' ):function_name 206 | 207 | computed_function_name ::= 5( variable | atom | '(' expression ')' ) 208 | 209 | expr_macro_application ::= >1( '?' _macro_name ( ( '(' ( expression ( ',' expression )* )? ')' ):arguments )? ) 210 | 211 | _macro_name ::= variable 212 | | atom 213 | 214 | variable ::= /[_A-Z\xC0-\xD6\xD8-\xDE][_@a-zA-Z0-9\xC0-\xD6\xD8-\xDE\xDF-\xF6\xF8-\xFF]*/ 215 | 216 | term ::= atom 217 | | binary_string 218 | | char 219 | | float 220 | | integer 221 | | list 222 | | tuple 223 | | map 224 | | record 225 | | string 226 | 227 | list ::= '[' ( expression ( ',' expression )* )? ']' 228 | 229 | tuple ::= '{' ( expression ( ',' expression )* )? '}' 230 | 231 | atom ::= ( _unquoted_atom | _quoted_atom ):value 232 | 233 | _unquoted_atom ::= /[a-z\xDF-\xF6\xF8-\xFF][_@a-zA-Z0-9\xC0-\xD6\xD8-\xDE\xDF-\xF6\xF8-\xFF]*/ 234 | 235 | _quoted_atom ::= "'" ( /[^'\\]+/ | _escape )* "'" 236 | 237 | integer ::= /-?2#[01_]+/ 238 | | /-?16#[a-fA-F0-9_]+/ 239 | | /-?([\d*_]*#)?[\d_]+/ 240 | 241 | float ::= /-?([\d_]*#)?[\d_]+\.[\d_]+(e-?[\d_]+)?/ 242 | 243 | string ::= '"' ( /[^"\\]+/ | _escape )* '"' 244 | 245 | char ::= '$' ( /[^\\]/ | _escape ) 246 | 247 | _escape ::= @( '\\' ( /[0-7]{1,3}/ | /x[0-9a-fA-F]{2}/ | /x{[0-9a-fA-F]+}/ | '\n' | /[nrtvbfesd]/ ) ) 248 | 249 | binary_string ::= '<<' ( bin_part ( ',' bin_part )* )? '>>' 250 | 251 | bin_part ::= ( integer | float | string ) bin_sized? bin_type_list? 252 | | '(' expression ')' bin_sized? bin_type_list? 253 | 254 | bin_sized ::= /:/ integer 255 | 256 | bin_type_list ::= /\// bin_type ( '-' bin_type )* 257 | 258 | bin_type ::= 'big' 259 | | 'binary' 260 | | 'bits' 261 | | 'bitstring' 262 | | 'bytes' 263 | | 'float' 264 | | 'integer' 265 | | 'little' 266 | | 'native' 267 | | 'signed' 268 | | 'unsigned' 269 | | 'utf16' 270 | | 'utf32' 271 | | 'utf8' 272 | 273 | map ::= '#' '{' ( map_entry ( ',' map_entry )* )? '}' 274 | 275 | map_entry ::= term ( '=>' | ':=' ) expression 276 | 277 | record ::= '#' atom '{' ( record_field ( ',' record_field )* )? '}' 278 | 279 | record_field ::= term '=' expression 280 | 281 | -------------------------------------------------------------------------------- /examples/fact.c: -------------------------------------------------------------------------------- 1 | /* Used as an input example for the C11 parser. */ 2 | extern int printf(const char* format, ...); 3 | static int fact(int n) { 4 | if(n == 0) 5 | return 1; 6 | else 7 | return n * fact(n-1); 8 | } 9 | int main() { 10 | printf("%d\n", fact(10)); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /examples/fact.lua: -------------------------------------------------------------------------------- 1 | -- Used as an input example for the Lua parser. 2 | local function fact(n) 3 | if n == 0 then 4 | return 1 5 | else 6 | return n * fact(n-1) 7 | end 8 | end 9 | print(fact(10)) 10 | -------------------------------------------------------------------------------- /examples/go.ebnf: -------------------------------------------------------------------------------- 1 | ; repository: https://github.com/tree-sitter/tree-sitter-go.git 2 | ; commit: 81a11f8252998ee6b98d59e6da91fc307491e53d 3 | ; json from: tree-sitter-go/src/grammar.json 4 | ; From /tmp/tslua/go0.json 5 | ; EBNF to generate grammar.js at 6 | ; https://mingodad.github.io/lua-wasm-playground/ 7 | ; based on https://github.com/eatkins/tree-sitter-ebnf-generator 8 | ; see also https://mingodad.github.io/plgh/json2ebnf.html 9 | 10 | 11 | extras ::= { 12 | comment 13 | /\s/ 14 | } 15 | 16 | supertypes ::= { 17 | _expression 18 | _type 19 | _simple_type 20 | _statement 21 | _simple_statement 22 | } 23 | 24 | inline ::= { 25 | _type 26 | _type_identifier 27 | _field_identifier 28 | _package_identifier 29 | _top_level_declaration 30 | _string_literal 31 | _interface_elem 32 | } 33 | 34 | conflicts ::= { 35 | { _simple_type _expression } 36 | { _simple_type generic_type _expression } 37 | { qualified_type _expression } 38 | { generic_type _simple_type } 39 | { parameter_declaration _simple_type } 40 | { type_parameter_declaration _simple_type _expression } 41 | { type_parameter_declaration _expression } 42 | { type_parameter_declaration _simple_type generic_type _expression } 43 | } 44 | 45 | word ::= identifier 46 | 47 | rules: 48 | 49 | source_file ::= ( _statement ( /\n/ | ';' | '\0' ) | _top_level_declaration ( /\n/ | ';' | '\0' ) )* _top_level_declaration? 50 | 51 | _top_level_declaration ::= package_clause 52 | | function_declaration 53 | | method_declaration 54 | | import_declaration 55 | 56 | package_clause ::= 'package' _package_identifier 57 | 58 | import_declaration ::= 'import' ( import_spec | import_spec_list ) 59 | 60 | import_spec ::= ( ( dot | blank_identifier | _package_identifier ):name )? _string_literal:path 61 | 62 | dot ::= '.' 63 | 64 | blank_identifier ::= '_' 65 | 66 | import_spec_list ::= '(' ( import_spec ( ( /\n/ | ';' | '\0' ) import_spec )* ( /\n/ | ';' | '\0' )? )? ')' 67 | 68 | _declaration ::= const_declaration 69 | | type_declaration 70 | | var_declaration 71 | 72 | const_declaration ::= 'const' ( const_spec | '(' ( const_spec ( /\n/ | ';' | '\0' ) )* ')' ) 73 | 74 | const_spec ::= <0( ( identifier ( ',' identifier )* ):name ( ( _type:type )? '=' expression_list:value )? ) 75 | 76 | var_declaration ::= 'var' ( var_spec | var_spec_list ) 77 | 78 | var_spec ::= identifier:name ( ',' identifier:name )* ( _type:type ( '=' expression_list:value )? | '=' expression_list:value ) 79 | 80 | var_spec_list ::= '(' ( var_spec ( /\n/ | ';' | '\0' ) )* ')' 81 | 82 | function_declaration ::= >1( 'func' identifier:name type_parameter_list?:type_parameters parameter_list:parameters ( parameter_list | _simple_type )?:result block?:body ) 83 | 84 | method_declaration ::= >1( 'func' parameter_list:receiver _field_identifier:name parameter_list:parameters ( parameter_list | _simple_type )?:result block?:body ) 85 | 86 | type_parameter_list ::= '[' type_parameter_declaration ( ',' type_parameter_declaration )* ','? ']' 87 | 88 | type_parameter_declaration ::= identifier:name ( ',' identifier:name )* ( type_elem -> type_constraint ):type 89 | 90 | parameter_list ::= '(' ( ( ( parameter_declaration | variadic_parameter_declaration ) ( ',' ( parameter_declaration | variadic_parameter_declaration ) )* )? ','? )? ')' 91 | 92 | parameter_declaration ::= <0( ( identifier:name ( ',' identifier:name )* )? _type:type ) 93 | 94 | variadic_parameter_declaration ::= identifier?:name '...' _type:type 95 | 96 | type_alias ::= _type_identifier:name '=' _type:type 97 | 98 | type_declaration ::= 'type' ( type_spec | type_alias | '(' ( ( type_spec | type_alias ) ( /\n/ | ';' | '\0' ) )* ')' ) 99 | 100 | type_spec ::= _type_identifier:name type_parameter_list?:type_parameters _type:type 101 | 102 | field_name_list ::= _field_identifier ( ',' _field_identifier )* 103 | 104 | expression_list ::= _expression ( ',' _expression )* 105 | 106 | _type ::= _simple_type 107 | | parenthesized_type 108 | 109 | parenthesized_type ::= '(' _type ')' 110 | 111 | _simple_type ::= ~-1( _type_identifier ) 112 | | generic_type 113 | | qualified_type 114 | | pointer_type 115 | | struct_type 116 | | interface_type 117 | | array_type 118 | | slice_type 119 | | map_type 120 | | channel_type 121 | | function_type 122 | | negated_type 123 | 124 | generic_type ::= ~1( ( _type_identifier | qualified_type | negated_type ):type type_arguments:type_arguments ) 125 | 126 | type_arguments ::= ~2( '[' type_elem ( ',' type_elem )* ','? ']' ) 127 | 128 | pointer_type ::= 6( '*' _type ) 129 | 130 | array_type ::= >0( '[' _expression:length ']' _type:element ) 131 | 132 | implicit_length_array_type ::= '[' '...' ']' _type:element 133 | 134 | slice_type ::= >0( '[' ']' _type:element ) 135 | 136 | struct_type ::= 'struct' field_declaration_list 137 | 138 | negated_type ::= <0( '~' _type ) 139 | 140 | field_declaration_list ::= '{' ( field_declaration ( ( /\n/ | ';' | '\0' ) field_declaration )* ( /\n/ | ';' | '\0' )? )? '}' 141 | 142 | field_declaration ::= ( _field_identifier:name ( ',' _field_identifier:name )* _type:type | '*'? ( _type_identifier | qualified_type | generic_type ):type ) _string_literal?:tag 143 | 144 | interface_type ::= 'interface' '{' ( _interface_elem ( ( /\n/ | ';' | '\0' ) _interface_elem )* ( /\n/ | ';' | '\0' )? )? '}' 145 | 146 | _interface_elem ::= method_elem 147 | | type_elem 148 | 149 | method_elem ::= _field_identifier:name parameter_list:parameters ( parameter_list | _simple_type )?:result 150 | 151 | type_elem ::= _type ( '|' _type )* 152 | 153 | map_type ::= >0( 'map' '[' _type:key ']' _type:value ) 154 | 155 | channel_type ::= <0( 'chan' _type:value | 'chan' '<-' _type:value | 6( '<-' 'chan' _type:value ) ) 156 | 157 | function_type ::= >0( 'func' parameter_list:parameters ( parameter_list | _simple_type )?:result ) 158 | 159 | block ::= '{' _statement_list? '}' 160 | 161 | _statement_list ::= _statement ( ( /\n/ | ';' | '\0' ) _statement )* ( ( /\n/ | ';' | '\0' ) ( empty_labeled_statement -> labeled_statement )? )? 162 | | empty_labeled_statement -> labeled_statement 163 | 164 | _statement ::= _declaration 165 | | _simple_statement 166 | | return_statement 167 | | go_statement 168 | | defer_statement 169 | | if_statement 170 | | for_statement 171 | | expression_switch_statement 172 | | type_switch_statement 173 | | select_statement 174 | | labeled_statement 175 | | fallthrough_statement 176 | | break_statement 177 | | continue_statement 178 | | goto_statement 179 | | block 180 | | empty_statement 181 | 182 | empty_statement ::= ';' 183 | 184 | _simple_statement ::= expression_statement 185 | | send_statement 186 | | inc_statement 187 | | dec_statement 188 | | assignment_statement 189 | | short_var_declaration 190 | 191 | expression_statement ::= _expression 192 | 193 | send_statement ::= _expression:channel '<-' _expression:value 194 | 195 | receive_statement ::= ( expression_list:left ( '=' | ':=' ) )? _expression:right 196 | 197 | inc_statement ::= _expression '++' 198 | 199 | dec_statement ::= _expression '--' 200 | 201 | assignment_statement ::= expression_list:left ( '*=' | '/=' | '%=' | '<<=' | '>>=' | '&=' | '&^=' | '+=' | '-=' | '|=' | '^=' | '=' ):operator expression_list:right 202 | 203 | short_var_declaration ::= expression_list:left ':=' expression_list:right 204 | 205 | labeled_statement ::= ( identifier -> label_name ):label ':' _statement 206 | 207 | empty_labeled_statement ::= ( identifier -> label_name ):label ':' 208 | 209 | fallthrough_statement ::= <0( 'fallthrough' ) 210 | 211 | break_statement ::= 'break' ( identifier -> label_name )? 212 | 213 | continue_statement ::= 'continue' ( identifier -> label_name )? 214 | 215 | goto_statement ::= 'goto' identifier -> label_name 216 | 217 | return_statement ::= 'return' expression_list? 218 | 219 | go_statement ::= 'go' _expression 220 | 221 | defer_statement ::= 'defer' _expression 222 | 223 | if_statement ::= 'if' ( _simple_statement:initializer ';' )? _expression:condition block:consequence ( 'else' ( block | if_statement ):alternative )? 224 | 225 | for_statement ::= 'for' ( _expression | for_clause | range_clause )? block:body 226 | 227 | for_clause ::= _simple_statement?:initializer ';' _expression?:condition ';' _simple_statement?:update 228 | 229 | range_clause ::= ( expression_list:left ( '=' | ':=' ) )? 'range' _expression:right 230 | 231 | expression_switch_statement ::= 'switch' ( _simple_statement:initializer ';' )? _expression?:value '{' ( expression_case | default_case )* '}' 232 | 233 | expression_case ::= 'case' expression_list:value ':' _statement_list? 234 | 235 | default_case ::= 'default' ':' _statement_list? 236 | 237 | type_switch_statement ::= 'switch' _type_switch_header '{' ( type_case | default_case )* '}' 238 | 239 | _type_switch_header ::= ( _simple_statement:initializer ';' )? ( expression_list:alias ':=' )? _expression:value '.' '(' 'type' ')' 240 | 241 | type_case ::= 'case' ( _type ( ',' _type )* ):type ':' _statement_list? 242 | 243 | select_statement ::= 'select' '{' ( communication_case | default_case )* '}' 244 | 245 | communication_case ::= 'case' ( send_statement | receive_statement ):communication ':' _statement_list? 246 | 247 | _expression ::= unary_expression 248 | | binary_expression 249 | | selector_expression 250 | | index_expression 251 | | slice_expression 252 | | call_expression 253 | | type_assertion_expression 254 | | type_conversion_expression 255 | | type_instantiation_expression 256 | | identifier 257 | | ( 'new' | 'make' ) -> identifier 258 | | composite_literal 259 | | func_literal 260 | | _string_literal 261 | | int_literal 262 | | float_literal 263 | | imaginary_literal 264 | | rune_literal 265 | | nil 266 | | true 267 | | false 268 | | iota 269 | | parenthesized_expression 270 | 271 | parenthesized_expression ::= '(' _expression ')' 272 | 273 | call_expression ::= 7( ( ( 'new' | 'make' ) -> identifier ):function ( special_argument_list -> argument_list ):arguments | _expression:function type_arguments?:type_arguments argument_list:arguments ) 274 | 275 | variadic_argument ::= >0( _expression '...' ) 276 | 277 | special_argument_list ::= '(' ( _type ( ',' _expression )* ','? )? ')' 278 | 279 | argument_list ::= '(' ( ( _expression | variadic_argument ) ( ',' ( _expression | variadic_argument ) )* ','? )? ')' 280 | 281 | selector_expression ::= 7( _expression:operand '.' _field_identifier:field ) 282 | 283 | index_expression ::= 7( _expression:operand '[' _expression:index ']' ) 284 | 285 | slice_expression ::= 7( _expression:operand '[' ( _expression?:start ':' _expression?:end | _expression?:start ':' _expression:end ':' _expression:capacity ) ']' ) 286 | 287 | type_assertion_expression ::= 7( _expression:operand '.' '(' _type:type ')' ) 288 | 289 | type_conversion_expression ::= ~-1( _type:type '(' _expression:operand ','? ')' ) 290 | 291 | type_instantiation_expression ::= ~-1( _type:type '[' _type ( ',' _type )* ','? ']' ) 292 | 293 | composite_literal ::= -1( ( map_type | slice_type | array_type | implicit_length_array_type | struct_type | _type_identifier | generic_type | qualified_type ):type literal_value:body ) 294 | 295 | literal_value ::= '{' ( ( ( literal_element | keyed_element ) ( ',' ( literal_element | keyed_element ) )* )? ','? )? '}' 296 | 297 | literal_element ::= _expression 298 | | literal_value 299 | 300 | keyed_element ::= literal_element ':' literal_element 301 | 302 | func_literal ::= 'func' parameter_list:parameters ( parameter_list | _simple_type )?:result block:body 303 | 304 | unary_expression ::= 6( ( '+' | '-' | '!' | '^' | '*' | '&' | '<-' ):operator _expression:operand ) 305 | 306 | binary_expression ::= <5( _expression:left ( '*' | '/' | '%' | '<<' | '>>' | '&' | '&^' ):operator _expression:right ) 307 | | <4( _expression:left ( '+' | '-' | '|' | '^' ):operator _expression:right ) 308 | | <3( _expression:left ( '==' | '!=' | '<' | '<=' | '>' | '>=' ):operator _expression:right ) 309 | | <2( _expression:left '&&':operator _expression:right ) 310 | | <1( _expression:left '||':operator _expression:right ) 311 | 312 | qualified_type ::= _package_identifier:package '.' _type_identifier:name 313 | 314 | identifier ::= /[_\p{XID_Start}][_\p{XID_Continue}]*/ 315 | 316 | _type_identifier ::= identifier -> type_identifier 317 | 318 | _field_identifier ::= identifier -> field_identifier 319 | 320 | _package_identifier ::= identifier -> package_identifier 321 | 322 | _string_literal ::= raw_string_literal 323 | | interpreted_string_literal 324 | 325 | raw_string_literal ::= @( '`' /[^`]/* '`' ) 326 | 327 | interpreted_string_literal ::= '"' ( _interpreted_string_literal_basic_content | escape_sequence )* !( '"' ) 328 | 329 | _interpreted_string_literal_basic_content ::= !( 1( /[^"\n\\]+/ ) ) 330 | 331 | escape_sequence ::= !( '\\' ( /[^xuU]/ | /\d{2,3}/ | /x[0-9a-fA-F]{2,}/ | /u[0-9a-fA-F]{4}/ | /U[0-9a-fA-F]{8}/ ) ) 332 | 333 | int_literal ::= @( '0' ( 'b' | 'B' ) '_'? /[01]/ ( '_'? /[01]/ )* | '0' | /[1-9]/ ( '_'? /[0-9]/ ( '_'? /[0-9]/ )* )? | '0' ( 'o' | 'O' )? '_'? /[0-7]/ ( '_'? /[0-7]/ )* | '0' ( 'x' | 'X' ) '_'? /[0-9a-fA-F]/ ( '_'? /[0-9a-fA-F]/ )* ) 334 | 335 | float_literal ::= @( /[0-9]/ ( '_'? /[0-9]/ )* '.' ( /[0-9]/ ( '_'? /[0-9]/ )* )? ( ( 'e' | 'E' ) ( '+' | '-' )? /[0-9]/ ( '_'? /[0-9]/ )* )? | /[0-9]/ ( '_'? /[0-9]/ )* ( 'e' | 'E' ) ( '+' | '-' )? /[0-9]/ ( '_'? /[0-9]/ )* | '.' /[0-9]/ ( '_'? /[0-9]/ )* ( ( 'e' | 'E' ) ( '+' | '-' )? /[0-9]/ ( '_'? /[0-9]/ )* )? | '0' ( 'x' | 'X' ) ( '_'? /[0-9a-fA-F]/ ( '_'? /[0-9a-fA-F]/ )* '.' ( /[0-9a-fA-F]/ ( '_'? /[0-9a-fA-F]/ )* )? | '_'? /[0-9a-fA-F]/ ( '_'? /[0-9a-fA-F]/ )* | '.' /[0-9a-fA-F]/ ( '_'? /[0-9a-fA-F]/ )* ) ( 'p' | 'P' ) ( '+' | '-' )? /[0-9]/ ( '_'? /[0-9]/ )* ) 336 | 337 | imaginary_literal ::= @( ( /[0-9]/ ( '_'? /[0-9]/ )* | '0' ( 'b' | 'B' ) '_'? /[01]/ ( '_'? /[01]/ )* | '0' | /[1-9]/ ( '_'? /[0-9]/ ( '_'? /[0-9]/ )* )? | '0' ( 'o' | 'O' )? '_'? /[0-7]/ ( '_'? /[0-7]/ )* | '0' ( 'x' | 'X' ) '_'? /[0-9a-fA-F]/ ( '_'? /[0-9a-fA-F]/ )* | /[0-9]/ ( '_'? /[0-9]/ )* '.' ( /[0-9]/ ( '_'? /[0-9]/ )* )? ( ( 'e' | 'E' ) ( '+' | '-' )? /[0-9]/ ( '_'? /[0-9]/ )* )? | /[0-9]/ ( '_'? /[0-9]/ )* ( 'e' | 'E' ) ( '+' | '-' )? /[0-9]/ ( '_'? /[0-9]/ )* | '.' /[0-9]/ ( '_'? /[0-9]/ )* ( ( 'e' | 'E' ) ( '+' | '-' )? /[0-9]/ ( '_'? /[0-9]/ )* )? | '0' ( 'x' | 'X' ) ( '_'? /[0-9a-fA-F]/ ( '_'? /[0-9a-fA-F]/ )* '.' ( /[0-9a-fA-F]/ ( '_'? /[0-9a-fA-F]/ )* )? | '_'? /[0-9a-fA-F]/ ( '_'? /[0-9a-fA-F]/ )* | '.' /[0-9a-fA-F]/ ( '_'? /[0-9a-fA-F]/ )* ) ( 'p' | 'P' ) ( '+' | '-' )? /[0-9]/ ( '_'? /[0-9]/ )* ) 'i' ) 338 | 339 | rune_literal ::= @( "'" ( /[^'\\]/ | '\\' ( 'x' /[0-9a-fA-F]/ /[0-9a-fA-F]/ | /[0-7]/ /[0-7]/ /[0-7]/ | 'u' /[0-9a-fA-F]/ /[0-9a-fA-F]/ /[0-9a-fA-F]/ /[0-9a-fA-F]/ | 'U' /[0-9a-fA-F]/ /[0-9a-fA-F]/ /[0-9a-fA-F]/ /[0-9a-fA-F]/ /[0-9a-fA-F]/ /[0-9a-fA-F]/ /[0-9a-fA-F]/ /[0-9a-fA-F]/ | ( 'a' | 'b' | 'f' | 'n' | 'r' | 't' | 'v' | '\\' | "'" | '"' ) ) ) "'" ) 340 | 341 | nil ::= 'nil' 342 | 343 | true ::= 'true' 344 | 345 | false ::= 'false' 346 | 347 | iota ::= 'iota' 348 | 349 | comment ::= @( '//' /.*/ | '/*' /[^*]*\*+([^/*][^*]*\*+)*/ '/' ) 350 | 351 | -------------------------------------------------------------------------------- /examples/haxe.ebnf: -------------------------------------------------------------------------------- 1 | ; repository: https://github.com/Vet2L/tree-sitter-haxe.git 2 | ; commit: d32c2cd6679030b339714e5672111f813bdd3056 3 | ; json from: tree-sitter-haxe/src/grammar.json 4 | ; From /tmp/tslua/haxe0.json 5 | ; EBNF to generate grammar.js at 6 | ; https://mingodad.github.io/lua-wasm-playground/ 7 | ; based on https://github.com/eatkins/tree-sitter-ebnf-generator 8 | ; see also https://mingodad.github.io/plgh/json2ebnf.html 9 | 10 | 11 | extras ::= { 12 | comment 13 | /[\s\uFEFF\u2060\u200B\u00A0]/ 14 | } 15 | 16 | supertypes ::= { 17 | declaration 18 | } 19 | 20 | inline ::= { 21 | statement 22 | expression 23 | } 24 | 25 | conflicts ::= { 26 | { block object } 27 | { typedef_declaration type } 28 | { call_expression _constructor_call } 29 | { _rhs_expression pair } 30 | { _literal pair } 31 | { pair pair } 32 | { function_declaration } 33 | { function_type variable_declaration } 34 | { type function_type variable_declaration } 35 | { type _function_type_args } 36 | { structure_type_pair _function_type_args } 37 | { function_declaration variable_declaration } 38 | { _prefixUnaryOperator _arithmeticOperator } 39 | { _prefixUnaryOperator _postfixUnaryOperator } 40 | } 41 | 42 | word ::= identifier 43 | 44 | rules: 45 | 46 | module ::= statement* 47 | 48 | statement ::= <0( ( preprocessor_statement | import_statement | using_statement | package_statement | declaration | expression | conditional_statement | case_statement | throw_statement | block ) _semicolon? ) 49 | 50 | preprocessor_statement ::= >0( '#' ( !( 'if' | 'elseif' ) statement | !( 'else' | 'end' ) ) ) 51 | 52 | package_statement ::= 'package' -> keyword _lhs_expression:name _semicolon 53 | 54 | import_statement ::= 'import' -> keyword _lhs_expression:name _semicolon 55 | 56 | using_statement ::= 'using' -> keyword _lhs_expression:name _semicolon 57 | 58 | throw_statement ::= >0( 'throw' -> keyword expression ) 59 | 60 | _rhs_expression ::= >0( _literal | identifier | member_expression | call_expression ) 61 | 62 | _unaryExpression ::= <1( operator _rhs_expression | _rhs_expression operator ) 63 | 64 | runtime_type_check_expression ::= 20( '(' structure_type_pair -> "type_check" ')' ) 65 | 66 | switch_expression ::= >0( 'switch' -> keyword ( identifier | _parenthesized_expression ) ) 67 | 68 | switch_block ::= '{' case_statement* '}' 69 | 70 | case_statement ::= >0( 'case' -> keyword ( _rhs_expression | '_' -> _rhs_expression ) ':' statement | 'default' -> keyword ':' statement ) 71 | 72 | cast_expression ::= 'cast' -> keyword _rhs_expression 73 | | 'cast' -> keyword '(' _rhs_expression ( ',' type:type )? ')' 74 | 75 | type_trace_expression ::= '$type' -> keyword '(' _rhs_expression ')' 76 | 77 | _parenthesized_expression ::= '(' <0( expression ) + ')' 78 | 79 | range_expression ::= 1( identifier 'in' -> keyword ( integer _rangeOperator integer | identifier ) ) 80 | 81 | expression ::= _unaryExpression 82 | | subscript_expression 83 | | runtime_type_check_expression 84 | | cast_expression 85 | | type_trace_expression 86 | | range_expression 87 | | _parenthesized_expression 88 | | switch_expression 89 | | _rhs_expression ( operator _rhs_expression )* 90 | 91 | subscript_expression ::= <1( ( identifier | _parenthesized_expression | member_expression ) '[' expression:index ']' ) 92 | 93 | member_expression ::= >0( ( ( 'this' -> keyword | identifier ):object | _literal:literal ) ( @( '.' ) | '?' -> operator '.' ) ( _lhs_expression:member )+ ) 94 | 95 | _lhs_expression ::= 1( identifier | member_expression ) 96 | 97 | builtin_type ::= >0( 'Void' | 'Int' | 'Float' | 'Bool' | 'Null' ) 98 | 99 | _function_type_args ::= ( identifier ':' )? type ( ',' ( identifier ':' )? type )* 100 | 101 | function_type ::= >0( '(' ')' '->' type | type '->' type:return_type | '(' _function_type_args ')' '->' type ) 102 | 103 | type ::= >0( ( _lhs_expression:type_name | ( builtin_type -> identifier ):built_in ) type_params? | function_type | '(' type -> "type" ')' ) 104 | 105 | block ::= '{' statement* '}' 106 | 107 | metadata ::= ( @( '@' ) | @( '@:' ) ) _lhs_expression:name ( '(' expression ')' )? 108 | 109 | _arg_list ::= '(' ( expression ( ',' expression )* )? ')' 110 | 111 | conditional_statement ::= >1( ( 'if' -> keyword ):name _arg_list:arguments_list block? ( ( 'else' | 'else if' ) -> keyword block )? ) 112 | 113 | _call ::= 1( _lhs_expression:object type_params? _arg_list:arguments_list ) 114 | 115 | _constructor_call ::= ( 'new' -> keyword )? _call 116 | 117 | call_expression ::= _call 118 | | _constructor_call 119 | 120 | operator ::= _binaryOperator 121 | | _unaryOperator 122 | 123 | _unaryOperator ::= >0( _prefixUnaryOperator | _postfixUnaryOperator ) 124 | 125 | _prefixUnaryOperator ::= '~' 126 | | '!' 127 | | '-' 128 | | '++' 129 | | '--' 130 | 131 | _postfixUnaryOperator ::= '++' 132 | | '--' 133 | 134 | _binaryOperator ::= <0( _arithmeticOperator | _bitwiseOperator | _logicalOperator | _comparisonOperator | _miscOperator | _assignmentOperator | _compoundAssignmentOperator | _rangeOperator ) 135 | 136 | _arithmeticOperator ::= '%' 137 | | '*' 138 | | '/' 139 | | '+' 140 | | '-' 141 | 142 | _bitwiseOperator ::= '<<' 143 | | '>>' 144 | | '>>>' 145 | | '&' 146 | | '|' 147 | | '^' 148 | 149 | _logicalOperator ::= '&&' 150 | | '||' 151 | 152 | _comparisonOperator ::= '==' 153 | | '!=' 154 | | '<' 155 | | '<=' 156 | | '>' 157 | | '>=' 158 | 159 | _miscOperator ::= '=>' 160 | | '??' 161 | 162 | _assignmentOperator ::= '=' 163 | 164 | _compoundAssignmentOperator ::= ( _arithmeticOperator | _bitwiseOperator ) _assignmentOperator 165 | 166 | _rangeOperator ::= '...' 167 | 168 | declaration ::= interface_declaration 169 | | class_declaration 170 | | typedef_declaration 171 | | function_declaration 172 | | variable_declaration 173 | 174 | _access_identifier ::= ( 'default' | 'null' | 'get' | 'set' | 'dynamic' | 'never' ) -> keyword 175 | 176 | access_identifiers ::= '(' _access_identifier ( ',' _access_identifier )? ')' 177 | 178 | type_param ::= _lhs_expression 179 | | _lhs_expression type_params 180 | 181 | type_params ::= >1( '<' type_param ( ',' type_param )* '>' ) 182 | 183 | class_declaration ::= metadata* ( 'final' -> keyword | 'abstract' -> keyword )? 'class' -> keyword _lhs_expression:name type_params? ( 'extends' -> keyword _lhs_expression:super_class_name )? ( 'implements' -> keyword _lhs_expression:interface_name )*? block:body 184 | 185 | interface_declaration ::= ( 'final' -> keyword )? 'interface' -> keyword _lhs_expression:name type_params? ( 'extends' -> keyword _lhs_expression:interface_name )*? block:body 186 | 187 | typedef_declaration ::= metadata* 'typedef' -> keyword _lhs_expression:name type_params? '=' ( block | _lhs_expression | type ) 188 | 189 | function_declaration ::= metadata* keyword* 'function' -> keyword ( _lhs_expression:name | ( 'new' -> identifier ):name ) type_params? _function_arg_list ( ':' type:return_type )? ( block:body )? 190 | 191 | _function_arg_list ::= 1( '(' ( function_arg ( ',' function_arg )* )? ')' ) 192 | 193 | function_arg ::= 1( _lhs_expression:name '?'? ( ':' ( _lhs_expression | type | structure_type ) -> type )? ( _assignmentOperator _literal )? ) 194 | 195 | variable_declaration ::= metadata* keyword* ( 'var' -> keyword | 'final' -> keyword ) _lhs_expression:name access_identifiers? ( ':' '('*? type:type ')'*? )? ( operator expression )? _semicolon 196 | 197 | _literal ::= integer 198 | | float 199 | | string 200 | | bool 201 | | null 202 | | array 203 | | map 204 | | object 205 | | pair 206 | 207 | integer ::= /[\d_]+/ 208 | | /0x[a-fA-F\d_]+/ 209 | 210 | float ::= /[\d_]+[\.]+[\d_]*/ 211 | | /[\d_]+[\.]+[\d_]*e[\d_]*/ 212 | 213 | bool ::= 'true' 214 | | 'false' 215 | 216 | string ::= /\'/ ( interpolation | escape_sequence | /[^\']/ )* /\'/ 217 | | /\"/ ( escape_sequence | /[^\"]/ )* /\"/ 218 | 219 | null ::= 'null' 220 | 221 | array ::= '[' ( <0( expression ) ( ',' <0( expression ) )* )? ']' 222 | | '[' expression identifier ']' 223 | 224 | map ::= 1( '[' pair ( ',' pair )* ']' ) 225 | 226 | object ::= 1( '{' ( pair ( ',' pair )* )? '}' ) 227 | 228 | structure_type ::= 1( '{' ( structure_type_pair -> pair ( ',' structure_type_pair -> pair )* )? '}' ) 229 | 230 | structure_type_pair ::= <0( ( identifier ) ':' type ) 231 | 232 | pair ::= >0( ( identifier | string ) ':' expression | ( identifier | _literal ) '=>' expression ) 233 | 234 | interpolation ::= _interpolated_block 235 | | _interpolated_identifier 236 | 237 | _interpolated_block ::= '${' expression '}' 238 | 239 | _interpolated_identifier ::= '$' _lhs_expression 240 | | '${' _lhs_expression '}' 241 | 242 | _interpolated_expression ::= '$' !( '{' ) expression '}' 243 | 244 | escape_sequence ::= !( '\\' ( /[^xu0-7]/ | /[0-7]{1,3}/ | /x[0-9a-fA-F]{2}/ | /u[0-9a-fA-F]{4}/ | /u{[0-9a-fA-F]+}/ ) ) 245 | 246 | comment ::= @( '//' /.*/ | '/*' /[^*]*\*+([^/*][^*]*\*+)*/ '/' ) 247 | 248 | keyword ::= >0( 'abstract' | 'break' | 'case' | 'cast' | 'catch' | 'class' | 'continue' | 'default' | 'do' | 'dynamic' | 'else' | 'enum' | 'extends' | 'extern' | 'final' | 'for' | 'function' | 'if' | 'implements' | 'import' | 'in' | 'inline' | 'interface' | 'macro' | 'new' | 'operator' | 'overload' | 'override' | 'package' | 'private' | 'public' | 'return' | 'static' | 'switch' | 'this' | 'throw' | 'try' | 'typedef' | 'untyped' | 'using' | 'var' | 'while' ) 249 | 250 | identifier ::= /[a-zA-Z_]+[a-zA-Z0-9]*/ 251 | 252 | _semicolon ::= ';' 253 | 254 | -------------------------------------------------------------------------------- /examples/html.ebnf: -------------------------------------------------------------------------------- 1 | ; repository: https://github.com/tree-sitter/tree-sitter-html.git 2 | ; commit: 14bdaf0da9e26e2de9b30178c2242539d2b0b285 3 | ; json from: tree-sitter-html/src/grammar.json 4 | ; From /tmp/tslua/html0.json 5 | ; EBNF to generate grammar.js at 6 | ; https://mingodad.github.io/lua-wasm-playground/ 7 | ; based on https://github.com/eatkins/tree-sitter-ebnf-generator 8 | ; see also https://mingodad.github.io/plgh/json2ebnf.html 9 | 10 | 11 | externals ::= { 12 | _start_tag_name 13 | _script_start_tag_name 14 | _style_start_tag_name 15 | _end_tag_name 16 | erroneous_end_tag_name 17 | '/>' 18 | _implicit_end_tag 19 | raw_text 20 | comment 21 | } 22 | 23 | extras ::= { 24 | comment 25 | /\s+/ 26 | } 27 | 28 | rules: 29 | 30 | document ::= _node* 31 | 32 | doctype ::= ' "doctype" /[^>]+/ '>' 33 | 34 | _doctype ::= /[Dd][Oo][Cc][Tt][Yy][Pp][Ee]/ 35 | 36 | _node ::= doctype 37 | | entity 38 | | text 39 | | element 40 | | script_element 41 | | style_element 42 | | erroneous_end_tag 43 | 44 | element ::= start_tag _node* ( end_tag | _implicit_end_tag ) 45 | | self_closing_tag 46 | 47 | script_element ::= script_start_tag -> start_tag raw_text? end_tag 48 | 49 | style_element ::= style_start_tag -> start_tag raw_text? end_tag 50 | 51 | start_tag ::= '<' _start_tag_name -> tag_name attribute* '>' 52 | 53 | script_start_tag ::= '<' _script_start_tag_name -> tag_name attribute* '>' 54 | 55 | style_start_tag ::= '<' _style_start_tag_name -> tag_name attribute* '>' 56 | 57 | self_closing_tag ::= '<' _start_tag_name -> tag_name attribute* '/>' 58 | 59 | end_tag ::= ' tag_name '>' 60 | 61 | erroneous_end_tag ::= '' 62 | 63 | attribute ::= attribute_name ( '=' ( attribute_value | quoted_attribute_value ) )? 64 | 65 | attribute_name ::= /[^<>"'/=\s]+/ 66 | 67 | attribute_value ::= /[^<>"'=\s]+/ 68 | 69 | entity ::= /&(#([xX][0-9a-fA-F]{1,6}|[0-9]{1,5})|[A-Za-z]{1,30});?/ 70 | 71 | quoted_attribute_value ::= "'" ( /[^']+/ -> attribute_value )? "'" 72 | | '"' ( /[^"]+/ -> attribute_value )? '"' 73 | 74 | text ::= /[^<>&\s]([^<>&]*[^<>&\s])?/ 75 | 76 | -------------------------------------------------------------------------------- /examples/ld.ebnf: -------------------------------------------------------------------------------- 1 | ; repository: https://github.com/mtoohey31/tree-sitter-ld 2 | ; commit: 0e9695ae0ede47b8744a8e2ad44d4d40c5d4e4c9 3 | ; json from: tree-sitter-ld/src/grammar.json 4 | ; From /tmp/tslua/ld0.json 5 | ; EBNF to generate grammar.js at 6 | ; https://mingodad.github.io/lua-wasm-playground/ 7 | ; based on https://github.com/eatkins/tree-sitter-ebnf-generator 8 | ; see also https://mingodad.github.io/plgh/json2ebnf.html 9 | 10 | 11 | extras ::= { 12 | /\s/ 13 | comment 14 | } 15 | 16 | word ::= NAME 17 | 18 | rules: 19 | 20 | script_file ::= ifile_p1* 21 | 22 | extern_name_list ::= NAME ( ','? NAME )* 23 | 24 | filename ::= NAME 25 | 26 | ifile_p1 ::= memory 27 | | sections 28 | | phdrs 29 | | startup 30 | | high_level_library 31 | | low_level_library 32 | | floating_point_support 33 | | statement_anywhere 34 | | version 35 | | ';' 36 | | 'TARGET' '(' NAME ')' 37 | | 'SEARCH_DIR' '(' filename ')' 38 | | 'OUTPUT' '(' filename ')' 39 | | 'OUTPUT_FORMAT' '(' NAME ')' 40 | | 'OUTPUT_FORMAT' '(' NAME ',' NAME ',' NAME ')' 41 | | 'OUTPUT_ARCH' '(' NAME ')' 42 | | 'FORCE_COMMON_ALLOCATION' 43 | | 'FORCE_GROUP_ALLOCATION' 44 | | 'INHIBIT_COMMON_ALLOCATION' 45 | | 'INPUT' '(' input_list ')' 46 | | 'GROUP' '(' input_list ')' 47 | | 'MAP' '(' filename ')' 48 | | 'INCLUDE' filename 49 | | 'NOCROSSREFS' '(' nocrossref_list? ')' 50 | | 'NOCROSSREFS_TO' '(' nocrossref_list? ')' 51 | | 'EXTERN' '(' extern_name_list ')' 52 | | 'INSERT' 'AFTER' NAME 53 | | 'INSERT' 'BEFORE' NAME 54 | | 'REGION_ALIAS' '(' NAME ',' NAME ')' 55 | | 'LD_FEATURE' '(' NAME ')' 56 | 57 | input_list ::= ( NAME | LNAME | 'AS_NEEDED' '(' input_list ')' ) ( ','? ( NAME | LNAME | 'AS_NEEDED' '(' input_list ')' ) )* 58 | 59 | sections ::= 'SECTIONS' '{' sec_or_group_p1? '}' 60 | 61 | sec_or_group_p1 ::= ( section | statement_anywhere )+ 62 | 63 | statement_anywhere ::= 'ENTRY' '(' NAME ')' 64 | | assignment separator 65 | | 'ASSERT' '(' exp ',' NAME ')' 66 | 67 | section_name_spec ::= wildcard_maybe_reverse 68 | | ( 'SORT_BY_NAME' | 'SORT' | 'SORT_BY_ALIGNMENT' | 'SORT_NONE' | 'SORT_BY_INIT_PRIORITY' ) '(' wildcard_maybe_reverse ')' 69 | | ( 'SORT_BY_NAME' | 'SORT' ) '(' ( 'SORT_BY_ALIGNMENT' | 'SORT_BY_NAME' | 'SORT' ) '(' wildcard_maybe_reverse ')' ')' 70 | | 'SORT_BY_ALIGNMENT' '(' ( 'SORT_BY_NAME' | 'SORT' | 'SORT_BY_ALIGNMENT' ) '(' wildcard_maybe_reverse ')' ')' 71 | | 'REVERSE' '(' ( 'SORT_BY_NAME' | 'SORT' | 'SORT_BY_INIT_PRIORITY' ) '(' wildcard_maybe_exclude ')' ')' 72 | 73 | wildcard_maybe_exclude ::= ( 'EXCLUDE_FILE' '(' exclude_name_list ')' )? wildcard_name 74 | 75 | wildcard_maybe_reverse ::= wildcard_maybe_exclude 76 | | 'REVERSE' '(' wildcard_maybe_exclude ')' 77 | 78 | filename_spec ::= wildcard_maybe_reverse 79 | | ( 'SORT_BY_NAME' | 'SORT' | 'SORT_NONE' ) '(' wildcard_maybe_reverse ')' 80 | | 'REVERSE' '(' ( 'SORT_BY_NAME' | 'SORT' ) '(' wildcard_maybe_exclude ')' ')' 81 | 82 | sect_flag_list ::= wildcard_name ( '&' wildcard_name )* 83 | 84 | sect_flags ::= 'INPUT_SECTION_FLAGS' '(' sect_flag_list ')' 85 | 86 | exclude_name_list ::= wildcard_name+ 87 | 88 | section_name_list ::= section_name_spec ( ','? section_name_spec )* 89 | 90 | input_section_spec_no_keep ::= NAME 91 | | sect_flags NAME 92 | | sect_flags? '[' section_name_list ']' 93 | | sect_flags? filename_spec '(' section_name_list ')' 94 | 95 | input_section_spec ::= input_section_spec_no_keep 96 | | 'KEEP' '(' input_section_spec_no_keep ')' 97 | 98 | statement ::= ';' 99 | | assignment separator 100 | | 'CREATE_OBJECT_SYMBOLS' 101 | | 'CONSTRUCTORS' 102 | | ( 'SORT_BY_NAME' | 'SORT' ) '(' 'CONSTRUCTORS' ')' 103 | | input_section_spec 104 | | length '(' mustbe_exp ')' 105 | | 'ASCIZ' NAME 106 | | 'FILL' '(' fill_exp ')' 107 | | 'LINKER_VERSION' 108 | | 'ASSERT' '(' exp ',' NAME ')' separator 109 | | 'INCLUDE' filename 110 | 111 | statement_list ::= statement+ 112 | 113 | length ::= 'QUAD' 114 | | 'SQUAD' 115 | | 'LONG' 116 | | 'SHORT' 117 | | 'BYTE' 118 | 119 | fill_exp ::= mustbe_exp 120 | 121 | assign_op ::= '+=' 122 | | '-=' 123 | | '*=' 124 | | '/=' 125 | | '<<=' 126 | | '>>=' 127 | | '&=' 128 | | '|=' 129 | | '^=' 130 | 131 | separator ::= ';' 132 | | ',' 133 | 134 | assignment ::= NAME '=' mustbe_exp 135 | | NAME assign_op mustbe_exp 136 | | ( 'HIDDEN' | 'PROVIDE' | 'PROVIDE_HIDDEN' ) '(' NAME '=' mustbe_exp ')' 137 | 138 | memory ::= 'MEMORY' '{' memory_spec_list? '}' 139 | 140 | memory_spec_list ::= memory_spec ( ','? memory_spec )* 141 | 142 | memory_spec ::= NAME attributes? ':' origin_spec ','? length_spec 143 | | 'INCLUDE' filename 144 | 145 | origin_spec ::= ( 'ORIGIN' | 'o' | 'org' ) '=' mustbe_exp 146 | 147 | length_spec ::= ( 'LENGTH' | 'l' | 'len' ) '=' mustbe_exp 148 | 149 | attributes ::= '(' attributes_list ')' 150 | 151 | attributes_list ::= attributes_string+ 152 | 153 | attributes_string ::= '!'? NAME 154 | 155 | startup ::= 'STARTUP' '(' filename ')' 156 | 157 | high_level_library ::= 'HLL' '(' high_level_library_NAME_list? ')' 158 | 159 | high_level_library_NAME_list ::= filename ( ','? filename )* 160 | 161 | low_level_library ::= 'SYSLIB' '(' low_level_library_NAME_list? ')' 162 | 163 | low_level_library_NAME_list ::= ','? filename+ ( ',' filename+ )* 164 | 165 | floating_point_support ::= 'FLOAT' 166 | | 'NOFLOAT' 167 | 168 | nocrossref_list ::= NAME ( ','? NAME )* ','? 169 | 170 | paren_script_name ::= '(' NAME ')' 171 | 172 | mustbe_exp ::= exp 173 | 174 | exp ::= <0( ( '-' | '!' | '+' | '~' ) exp | '(' exp ')' | ( 'NEXT' | 'ABSOLUTE' | 'DATA_SEGMENT_END' | 'BLOCK' | 'LOG2CEIL' ) '(' exp ')' | exp ( '*' | '/' | '%' | '+' | '-' | '<<' | '>>' | '==' | '!=' | '<=' | '>=' | '<' | '>' | '&' | '^' | '|' | '&&' | '||' ) exp | exp '?' exp ':' exp | ( 'DEFINED' | 'CONSTANT' ) '(' SYMBOLNAME ')' | INT | 'SIZEOF_HEADERS' | ( 'ALIGNOF' | 'SIZEOF' | 'ADDR' | 'LOADADDR' | 'ORIGIN' | 'LENGTH' ) paren_script_name | 'ALIGN' '(' exp ( ',' exp )? ')' | ( 'DATA_SEGMENT_ALIGN' | 'DATA_SEGMENT_RELRO_END' | 'MAX' | 'MIN' ) '(' exp ',' exp ')' | 'SEGMENT_START' '(' SYMBOLNAME ',' exp ')' | SYMBOLNAME | 'ASSERT' '(' exp ',' SYMBOLNAME ')' ) 175 | 176 | memspec_at ::= 'AT' '>' NAME 177 | 178 | at ::= 'AT' '(' exp ')' 179 | 180 | align ::= 'ALIGN' '(' exp ')' 181 | 182 | subalign ::= 'SUBALIGN' '(' exp ')' 183 | 184 | sect_constraint ::= 'ONLY_IF_RO' 185 | | 'ONLY_IF_RW' 186 | | 'SPECIAL' 187 | 188 | section ::= NAME opt_exp_with_type at? align? 'ALIGN_WITH_INPUT'? subalign? sect_constraint? '{' statement_list? '}' memspec? memspec_at? phdr_opt? ( '=' fill_exp )? ','? 189 | | 'OVERLAY' opt_exp_without_type 'NOCROSSREFS'? at? subalign? '{' overlay_section? '}' memspec? memspec_at? phdr_opt? ( '=' fill_exp )? ','? 190 | | 'GROUP' opt_exp_with_type '{' sec_or_group_p1? '}' 191 | | 'INCLUDE' filename 192 | 193 | type ::= 'NOLOAD' 194 | | 'DSECT' 195 | | 'COPY' 196 | | 'INFO' 197 | | 'OVERLAY' 198 | | 'READONLY' '(' 'TYPE' '=' exp ')' 199 | | 'READONLY' 200 | | 'TYPE' '=' exp 201 | 202 | atype ::= '(' type? ')' 203 | 204 | opt_exp_with_type ::= ( exp | 'BIND' '(' exp ')' ( 'BLOCK' '(' exp ')' )? )? atype? ':' 205 | 206 | opt_exp_without_type ::= exp? ':' 207 | 208 | memspec ::= '>' NAME 209 | 210 | phdr_opt ::= phdr_opt? ':' NAME 211 | 212 | phdrs ::= 'PHDRS' '{' phdr_list? '}' 213 | 214 | phdr_list ::= phdr+ 215 | 216 | phdr ::= NAME phdr_type phdr_qualifiers? ';' 217 | 218 | phdr_type ::= exp 219 | 220 | phdr_qualifiers ::= ( NAME phdr_val? | 'AT' '(' exp ')' )+ 221 | 222 | phdr_val ::= '(' exp ')' 223 | 224 | overlay_section ::= ( NAME '{' statement_list? '}' phdr_opt? ( '=' fill_exp )? ','? )+ 225 | 226 | version ::= 'VERSION' '{' vers_nodes '}' 227 | 228 | vers_nodes ::= vers_node+ 229 | 230 | vers_node ::= '{' vers_tag? '}' ';' 231 | | VERS_TAG '{' vers_tag? '}' verdep? ';' 232 | 233 | verdep ::= VERS_TAG+ 234 | 235 | vers_tag ::= vers_defns ';' 236 | | 'global' ':' vers_defns ';' 237 | | 'local' ':' vers_defns ';' 238 | | 'global' ':' vers_defns ';' 'local' ':' vers_defns ';' 239 | 240 | vers_defns ::= ( vers_defns ';' )? ( VERS_IDENTIFIER | 'extern' ( NAME '{' vers_defns ';'? '}' )? | 'global' | 'local' ) 241 | 242 | NAME ::= /=?[_a-zA-Z/.\\$~][_a-zA-Z0-9/.\\$~\-+:\[\],=]*|[_a-zA-Z.\\$][_a-zA-Z0-9/.\\$~]*|\/DISCARD\/|"[^"]*"/ 243 | 244 | SYMBOLNAME ::= /[_a-zA-Z.\\$][_a-zA-Z0-9/.\\$~]*|\/DISCARD\/|"[^"]*"/ 245 | 246 | LNAME ::= /-l[_a-zA-Z0-9/.\\$~\-+:\[\],=]+/ 247 | 248 | wildcard_name ::= /[_a-zA-Z0-9/.\\$~\-+:\[\],=?*^!]+/ 249 | 250 | INT ::= /\$[0-9A-Fa-f]+/ 251 | | /[0-9A-Fa-f]+[HhXxBbOoDd]/ 252 | | /((\$|0[xX])[0-9A-Fa-f]+|[0-9]+)[MKmk]?/ 253 | 254 | VERS_TAG ::= /[.$_a-zA-Z][._a-zA-Z0-9]*/ 255 | 256 | VERS_IDENTIFIER ::= /[*?.$_a-zA-Z\[\]\-!^\\]([*?.$_a-zA-Z0-9\[\]\-!^\\]|::)*/ 257 | 258 | comment ::= /\/\*([^*]|\*[^/])*\*\// 259 | 260 | -------------------------------------------------------------------------------- /examples/lua-ast-playground.lua: -------------------------------------------------------------------------------- 1 | local parserLuaCached 2 | function parserLua() 3 | if parserLuaCached then return parserLuaCached end 4 | --[[ 5 | This grammar is based on Lua 5.4 6 | As seen in https://www.lua.org/manual/5.4/manual.html#9 7 | ]] 8 | local Grammar = [==[ 9 | chunk <-- SHEBANG? SKIP Block (!.)^UnexpectedSyntax 10 | 11 | Block <== ( Label / Return / Break / Goto / Do / While / Repeat / If / ForNum / ForIn 12 | / FuncDef / FuncDecl / VarDecl / Assign / call / `;`)* 13 | Label <== `::` @NAME @`::` 14 | Return <== `return` exprlist? 15 | Break <== `break` 16 | Goto <== `goto` @NAME 17 | Do <== `do` Block @`end` 18 | While <== `while` @expr @`do` Block @`end` 19 | Repeat <== `repeat` Block @`until` @expr 20 | If <== `if` @expr @`then` Block (`elseif` @expr @`then` Block)* (`else` Block)? @`end` 21 | ForNum <== `for` Id `=` @expr @`,` @expr (`,` @expr)? @`do` Block @`end` 22 | ForIn <== `for` @idlist `in` @exprlist @`do` Block @`end` 23 | FuncDef <== `function` @funcname funcbody 24 | FuncDecl <== `local` `function` @Id funcbody 25 | VarDecl <== `local` @iddecllist (`=` @exprlist)? 26 | Assign <== varlist `=` @exprlist 27 | 28 | Number <== NUMBER->tonumber SKIP 29 | String <== STRING SKIP 30 | Boolean <== `false`->tofalse / `true`->totrue 31 | Nil <== `nil` 32 | Varargs <== `...` 33 | Id <== NAME 34 | IdDecl <== NAME (`<` @NAME @`>`)? 35 | Function <== `function` funcbody 36 | Table <== `{` (field (fieldsep field)* fieldsep?)? @`}` 37 | Paren <== `(` @expr @`)` 38 | Pair <== `[` @expr @`]` @`=` @expr / NAME `=` @expr 39 | 40 | Call <== callargs 41 | CallMethod <== `:` @NAME @callargs 42 | DotIndex <== `.` @NAME 43 | ColonIndex <== `:` @NAME 44 | KeyIndex <== `[` @expr @`]` 45 | 46 | indexsuffix <-- DotIndex / KeyIndex 47 | callsuffix <-- Call / CallMethod 48 | 49 | var <-- (exprprimary (callsuffix+ indexsuffix / indexsuffix)+)~>rfoldright / Id 50 | call <-- (exprprimary (indexsuffix+ callsuffix / callsuffix)+)~>foldleft 51 | exprsuffixed <-- (exprprimary (indexsuffix / callsuffix)*)~>foldleft 52 | funcname <-- (Id DotIndex* ColonIndex?)~>rfoldright 53 | 54 | funcbody <-- @`(` funcargs @`)` Block @`end` 55 | field <-- Pair / expr 56 | fieldsep <-- `,` / `;` 57 | 58 | callargs <-| `(` (expr (`,` @expr)*)? @`)` / Table / String 59 | idlist <-| Id (`,` @Id)* 60 | iddecllist <-| IdDecl (`,` @IdDecl)* 61 | funcargs <-| (Id (`,` Id)* (`,` Varargs)? / Varargs)? 62 | exprlist <-| expr (`,` @expr)* 63 | varlist <-| var (`,` @var)* 64 | 65 | opor :BinaryOp <== `or`->'or' @exprand 66 | opand :BinaryOp <== `and`->'and' @exprcmp 67 | opcmp :BinaryOp <== (`==`->'eq' / `~=`->'ne' / `<=`->'le' / `>=`->'ge' / `<`->'lt' / `>`->'gt') @exprbor 68 | opbor :BinaryOp <== `|`->'bor' @exprbxor 69 | opbxor :BinaryOp <== `~`->'bxor' @exprband 70 | opband :BinaryOp <== `&`->'band' @exprbshift 71 | opbshift :BinaryOp <== (`<<`->'shl' / `>>`->'shr') @exprconcat 72 | opconcat :BinaryOp <== `..`->'concat' @exprconcat 73 | oparit :BinaryOp <== (`+`->'add' / `-`->'sub') @exprfact 74 | opfact :BinaryOp <== (`*`->'mul' / `//`->'idiv' / `/`->'div' / `%`->'mod') @exprunary 75 | oppow :BinaryOp <== `^`->'pow' @exprunary 76 | opunary :UnaryOp <== (`not`->'not' / `#`->'len' / `-`->'unm' / `~`->'bnot') @exprunary 77 | 78 | expr <-- expror 79 | expror <-- (exprand opor*)~>foldleft 80 | exprand <-- (exprcmp opand*)~>foldleft 81 | exprcmp <-- (exprbor opcmp*)~>foldleft 82 | exprbor <-- (exprbxor opbor*)~>foldleft 83 | exprbxor <-- (exprband opbxor*)~>foldleft 84 | exprband <-- (exprbshift opband*)~>foldleft 85 | exprbshift <-- (exprconcat opbshift*)~>foldleft 86 | exprconcat <-- (exprarit opconcat*)~>foldleft 87 | exprarit <-- (exprfact oparit*)~>foldleft 88 | exprfact <-- (exprunary opfact*)~>foldleft 89 | exprunary <-- opunary / exprpow 90 | exprpow <-- (exprsimple oppow*)~>foldleft 91 | exprsimple <-- Nil / Boolean / Number / String / Varargs / Function / Table / exprsuffixed 92 | exprprimary <-- Id / Paren 93 | 94 | STRING <-- STRING_SHRT / STRING_LONG 95 | STRING_LONG <-- {:LONG_OPEN {LONG_CONTENT} @LONG_CLOSE:} 96 | STRING_SHRT <-- {:QUOTE_OPEN {~QUOTE_CONTENT~} @QUOTE_CLOSE:} 97 | QUOTE_OPEN <-- {:qe: ['"] :} 98 | QUOTE_CONTENT <-- (ESCAPE_SEQ / !(QUOTE_CLOSE / LINEBREAK) .)* 99 | QUOTE_CLOSE <-- =qe 100 | ESCAPE_SEQ <-- '\'->'' @ESCAPE 101 | ESCAPE <-- [\'"] / 102 | ('n' $10 / 't' $9 / 'r' $13 / 'a' $7 / 'b' $8 / 'v' $11 / 'f' $12)->tochar / 103 | ('x' {HEX_DIGIT^2} $16)->tochar / 104 | ('u' '{' {HEX_DIGIT^+1} '}' $16)->toutf8char / 105 | ('z' SPACE*)->'' / 106 | (DEC_DIGIT DEC_DIGIT^-1 !DEC_DIGIT / [012] DEC_DIGIT^2)->tochar / 107 | (LINEBREAK $10)->tochar 108 | 109 | NUMBER <-- {HEX_NUMBER / DEC_NUMBER} 110 | HEX_NUMBER <-- '0' [xX] @HEX_PREFIX ([pP] @EXP_DIGITS)? 111 | DEC_NUMBER <-- DEC_PREFIX ([eE] @EXP_DIGITS)? 112 | HEX_PREFIX <-- HEX_DIGIT+ ('.' HEX_DIGIT*)? / '.' HEX_DIGIT+ 113 | DEC_PREFIX <-- DEC_DIGIT+ ('.' DEC_DIGIT*)? / '.' DEC_DIGIT+ 114 | EXP_DIGITS <-- [+-]? DEC_DIGIT+ 115 | 116 | COMMENT <-- '--' (COMMENT_LONG / COMMENT_SHRT) 117 | COMMENT_LONG <-- (LONG_OPEN LONG_CONTENT @LONG_CLOSE)->0 118 | COMMENT_SHRT <-- (!LINEBREAK .)* 119 | 120 | LONG_CONTENT <-- (!LONG_CLOSE .)* 121 | LONG_OPEN <-- '[' {:eq: '='*:} '[' LINEBREAK? 122 | LONG_CLOSE <-- ']' =eq ']' 123 | 124 | NAME <-- !KEYWORD {NAME_PREFIX NAME_SUFFIX?} SKIP 125 | NAME_PREFIX <-- [_a-zA-Z] 126 | NAME_SUFFIX <-- [_a-zA-Z0-9]+ 127 | 128 | SHEBANG <-- '#!' (!LINEBREAK .)* LINEBREAK? 129 | SKIP <-- (SPACE+ / COMMENT)* 130 | LINEBREAK <-- %cn %cr / %cr %cn / %cn / %cr 131 | SPACE <-- %sp 132 | HEX_DIGIT <-- [0-9a-fA-F] 133 | DEC_DIGIT <-- [0-9] 134 | EXTRA_TOKENS <-- `[[` `[=` `--` -- unused rule, here just to force defining these tokens 135 | ]==] 136 | 137 | -- List of syntax errors 138 | local SyntaxErrorLabels = { 139 | ["Expected_::"] = "unclosed label, did you forget `::`?", 140 | ["Expected_)"] = "unclosed parenthesis, did you forget a `)`?", 141 | ["Expected_>"] = "unclosed angle bracket, did you forget a `>`?", 142 | ["Expected_]"] = "unclosed square bracket, did you forget a `]`?", 143 | ["Expected_}"] = "unclosed curly brace, did you forget a `}`?", 144 | ["Expected_LONG_CLOSE"] = "unclosed long string or comment, did your forget a ']]'?", 145 | ["Expected_QUOTE_CLOSE"]= "unclosed short string or comment, did your forget a quote?", 146 | ["Expected_("] = "expected parenthesis token `(`", 147 | ["Expected_,"] = "expected comma token `,`", 148 | ["Expected_="] = "expected equals token `=`", 149 | ["Expected_callargs"] = "expected arguments", 150 | ["Expected_expr"] = "expected an expression", 151 | ["Expected_exprand"] = "expected an expression after operator", 152 | ["Expected_exprcmp"] = "expected an expression after operator", 153 | ["Expected_exprbor"] = "expected an expression after operator", 154 | ["Expected_exprbxor"] = "expected an expression after operator", 155 | ["Expected_exprband"] = "expected an expression after operator", 156 | ["Expected_exprbshift"] = "expected an expression after operator", 157 | ["Expected_exprconcat"] = "expected an expression after operator", 158 | ["Expected_exprfact"] = "expected an expression after operator", 159 | ["Expected_exprunary"] = "expected an expression after operator", 160 | ["Expected_exprlist"] = "expected expressions", 161 | ["Expected_funcname"] = "expected a function name", 162 | ["Expected_do"] = "expected `do` keyword to begin a statement block", 163 | ["Expected_end"] = "expected `end` keyword to close a statement block", 164 | ["Expected_then"] = "expected `then` keyword to begin a statement block", 165 | ["Expected_until"] = "expected `until` keyword to close repeat statement", 166 | ["Expected_ESCAPE"] = "malformed escape sequence", 167 | ["Expected_EXP_DIGITS"] = "malformed exponential number", 168 | ["Expected_HEX_PREFIX"] = "malformed hexadecimal number", 169 | ["Expected_Id"] = "expected an identifier name", 170 | ["Expected_NAME"] = "expected an identifier name", 171 | ["Expected_IdDecl"] = "expected an identifier name declaration", 172 | ["Expected_iddecllist"] = "expected identifiers names declaration", 173 | ["Expected_idlist"] = "expected identifiers names", 174 | ["Expected_var"] = "expected a variable", 175 | ["UnexpectedSyntax"] = "unexpected syntax", 176 | } 177 | 178 | -- Compile grammar 179 | local lpegrex = require 'lpegrex' 180 | local patt = lpegrex.compile(Grammar) 181 | 182 | -- Parse Lua source into an AST. 183 | local function parse(source, name) 184 | local ast, errlabel, errpos = patt:match(source) 185 | if not ast then 186 | name = name or '' 187 | local lineno, colno, line = lpegrex.calcline(source, errpos) 188 | local colhelp = string.rep(' ', colno-1)..'^' 189 | local errmsg = SyntaxErrorLabels[errlabel] or errlabel 190 | error('syntax error: '..name..':'..lineno..':'..colno..': '..errmsg.. 191 | '\n'..line..'\n'..colhelp) 192 | end 193 | return ast 194 | end 195 | 196 | parserLuaCached = parse 197 | return parse 198 | end 199 | 200 | local lpegrex = require 'lpegrex' 201 | --lpegrex.debug = true 202 | local parse_lua = parserLua() -- require 'parsers.lua' 203 | 204 | -- Parse Lua source 205 | local ast = parse_lua(arg[1], "input_text") 206 | 207 | -- Print AST 208 | print(lpegrex.prettyast(ast)) 209 | -------------------------------------------------------------------------------- /examples/lua.ebnf: -------------------------------------------------------------------------------- 1 | ; repository: https://github.com/Azganoth/tree-sitter-lua.git 2 | ; commit: 6b02dfd7f07f36c223270e97eb0adf84e15a4cef 3 | ; json from: tree-sitter-lua/src/grammar.json 4 | ; From /tmp/tslua/lua0.json 5 | ; EBNF to generate grammar.js at 6 | ; https://mingodad.github.io/lua-wasm-playground/ 7 | ; based on https://github.com/eatkins/tree-sitter-ebnf-generator 8 | ; see also https://mingodad.github.io/plgh/json2ebnf.html 9 | 10 | 11 | externals ::= { 12 | _comment_start 13 | _comment_content 14 | _comment_end 15 | _string_start 16 | _string_content 17 | _string_end 18 | } 19 | 20 | extras ::= { 21 | /\s/ 22 | comment 23 | } 24 | 25 | supertypes ::= { 26 | prefix_expression 27 | expression 28 | statement 29 | } 30 | 31 | inline ::= { 32 | prefix 33 | field_separator 34 | } 35 | 36 | word ::= identifier 37 | 38 | rules: 39 | 40 | chunk ::= shebang? _block? 41 | 42 | shebang ::= /#!.*/ 43 | 44 | block ::= _block 45 | 46 | _block ::= return_statement 47 | | statement+ return_statement? 48 | 49 | return_statement ::= 'return' expression_list? empty_statement? 50 | 51 | statement ::= empty_statement 52 | | variable_assignment 53 | | local_variable_declaration 54 | | call 55 | | label_statement 56 | | goto_statement 57 | | break_statement 58 | | do_statement 59 | | while_statement 60 | | repeat_statement 61 | | if_statement 62 | | for_numeric_statement 63 | | for_generic_statement 64 | | function_definition_statement 65 | | local_function_definition_statement 66 | 67 | local_function_definition_statement ::= 'local' 'function' identifier:name _function_body 68 | 69 | function_definition_statement ::= 'function' ( identifier | _table_function_variable -> variable ):name _function_body 70 | 71 | _table_function_variable ::= _table_identifier ( _named_field_identifier | _method_identifier ) 72 | 73 | _table_identifier ::= ( identifier | _table_field_variable -> variable ):table 74 | 75 | _table_field_variable ::= _table_identifier _named_field_identifier 76 | 77 | for_generic_statement ::= 'for' ( _name_list -> variable_list ):left 'in' ( _value_list -> expression_list ):right 'do' ( block:body )? 'end' 78 | 79 | _name_list ::= identifier:name ( ',' identifier:name )* 80 | 81 | _value_list ::= expression:value ( ',' expression:value )* 82 | 83 | for_numeric_statement ::= 'for' identifier:name '=' expression:start ',' expression:end ( ',' expression:step )? 'do' ( block:body )? 'end' 84 | 85 | if_statement ::= 'if' expression:condition 'then' ( block:consequence )? ( elseif_clause:alternative )* ( else_clause:alternative )? 'end' 86 | 87 | elseif_clause ::= 'elseif' expression:condition 'then' ( block:consequence )? 88 | 89 | else_clause ::= 'else' ( block:body )? 90 | 91 | repeat_statement ::= 'repeat' ( block:body )? 'until' expression:condition 92 | 93 | while_statement ::= 'while' expression:condition 'do' ( block:body )? 'end' 94 | 95 | do_statement ::= 'do' ( block:body )? 'end' 96 | 97 | break_statement ::= 'break' 98 | 99 | goto_statement ::= 'goto' identifier:name 100 | 101 | label_statement ::= '::' identifier:name '::' 102 | 103 | local_variable_declaration ::= 'local' _local_variable_list -> variable_list ( '=' _value_list -> expression_list )? 104 | 105 | _local_variable_list ::= _local_variable -> variable ( ',' _local_variable -> variable )* 106 | 107 | _local_variable ::= identifier:name attribute? 108 | 109 | attribute ::= '<' identifier:name '>' 110 | 111 | variable_assignment ::= variable_list '=' _value_list -> expression_list 112 | 113 | variable_list ::= variable ( ',' variable )* 114 | 115 | empty_statement ::= ';' 116 | 117 | expression ::= nil 118 | | false 119 | | true 120 | | number 121 | | string 122 | | vararg_expression 123 | | function_definition 124 | | prefix_expression 125 | | table 126 | | unary_expression 127 | | binary_expression 128 | 129 | binary_expression ::= <1( expression:left 'or':operator expression:right ) 130 | | <2( expression:left 'and':operator expression:right ) 131 | | <3( expression:left '==':operator expression:right ) 132 | | <3( expression:left '~=':operator expression:right ) 133 | | <3( expression:left '<':operator expression:right ) 134 | | <3( expression:left '>':operator expression:right ) 135 | | <3( expression:left '<=':operator expression:right ) 136 | | <3( expression:left '>=':operator expression:right ) 137 | | <4( expression:left '|':operator expression:right ) 138 | | <5( expression:left '~':operator expression:right ) 139 | | <6( expression:left '&':operator expression:right ) 140 | | <7( expression:left '<<':operator expression:right ) 141 | | <7( expression:left '>>':operator expression:right ) 142 | | <9( expression:left '+':operator expression:right ) 143 | | <9( expression:left '-':operator expression:right ) 144 | | <10( expression:left '*':operator expression:right ) 145 | | <10( expression:left '/':operator expression:right ) 146 | | <10( expression:left '//':operator expression:right ) 147 | | <10( expression:left '%':operator expression:right ) 148 | | >8( expression:left '..':operator expression:right ) 149 | | >12( expression:left '^':operator expression:right ) 150 | 151 | unary_expression ::= <11( 'not':operator expression:argument ) 152 | | <11( '#':operator expression:argument ) 153 | | <11( '-':operator expression:argument ) 154 | | <11( '~':operator expression:argument ) 155 | 156 | table ::= '{' field_list? '}' 157 | 158 | field_list ::= field ( field_separator field )* field_separator? 159 | 160 | field ::= ( ( identifier:key | '[' expression:key ']' ) '=' )? expression:value 161 | 162 | field_separator ::= ',' 163 | | ';' 164 | 165 | prefix ::= variable 166 | | call 167 | | parenthesized_expression 168 | 169 | prefix_expression ::= prefix 170 | 171 | _prefix_expression ::= 13( prefix ) 172 | 173 | parenthesized_expression ::= '(' expression ')' 174 | 175 | call ::= ( _prefix_expression | _table_method_variable -> variable ):function argument_list:arguments 176 | 177 | _table_method_variable ::= prefix_expression:table _method_identifier 178 | 179 | _method_identifier ::= ':' identifier:method 180 | 181 | argument_list ::= '(' expression_list? ')' 182 | | table 183 | | string 184 | 185 | expression_list ::= expression ( ',' expression )* 186 | 187 | variable ::= identifier:name 188 | | _table_variable 189 | 190 | _table_variable ::= ( identifier | _table_variable -> variable | call | parenthesized_expression ):table ( _indexed_field_identifier | _named_field_identifier ) 191 | 192 | _named_field_identifier ::= '.' identifier:field 193 | 194 | _indexed_field_identifier ::= '[' expression:field ']' 195 | 196 | function_definition ::= 'function' _function_body 197 | 198 | _function_body ::= '(' ( parameter_list:parameters )? ')' ( block:body )? 'end' 199 | 200 | parameter_list ::= identifier:name ( ',' identifier:name )* ( ',' vararg_expression )? 201 | | vararg_expression 202 | 203 | vararg_expression ::= '...' 204 | 205 | string ::= _string_start _string_content? _string_end 206 | 207 | number ::= @( '-'? ( ( /[0-9]/+ | /[0-9]/+ '.' /[0-9]/* | /[0-9]/* '.' /[0-9]/+ ) ( ( 'e' | 'E' ) ( '+' | '-' )? /[0-9]/+ )? | ( '0x' | '0X' ) ( /[0-9a-fA-F]/+ | /[0-9a-fA-F]/+ '.' /[0-9a-fA-F]/* | /[0-9a-fA-F]/* '.' /[0-9a-fA-F]/+ ) ( ( 'p' | 'P' ) ( '+' | '-' )? /[0-9]/+ )? ) ) 208 | 209 | true ::= 'true' 210 | 211 | false ::= 'false' 212 | 213 | nil ::= 'nil' 214 | 215 | identifier ::= /[a-zA-Z_][0-9a-zA-Z_]*/ 216 | 217 | comment ::= _comment_start _comment_content? _comment_end 218 | 219 | -------------------------------------------------------------------------------- /examples/make.ebnf: -------------------------------------------------------------------------------- 1 | ; repository: https://github.com/alemuller/tree-sitter-make 2 | ; commit: a4b9187417d6be349ee5fd4b6e77b4172c6827dd 3 | ; json from: tree-sitter-make/src/grammar.json 4 | ; From /tmp/tslua/make0.json 5 | ; EBNF to generate grammar.js at 6 | ; https://mingodad.github.io/lua-wasm-playground/ 7 | ; based on https://github.com/eatkins/tree-sitter-ebnf-generator 8 | ; see also https://mingodad.github.io/plgh/json2ebnf.html 9 | 10 | 11 | extras ::= { 12 | /[\s]/ 13 | @( '\\' /\r?\n|\r/ ) -> "\\" 14 | comment 15 | } 16 | 17 | inline ::= { 18 | _targets 19 | _target_pattern 20 | _prerequisites_pattern 21 | _prerequisites 22 | _order_only_prerequisites 23 | _target_or_pattern_assignment 24 | _primary 25 | _name 26 | _string 27 | } 28 | 29 | word ::= word 30 | 31 | rules: 32 | 33 | makefile ::= _thing* 34 | 35 | _thing ::= rule 36 | | _variable_definition 37 | | _directive 38 | | _function !( /[\r\n]+/ ) 39 | 40 | rule ::= _ordinary_rule 41 | | _static_pattern_rule 42 | 43 | _ordinary_rule ::= >0( _targets ( ':' | '&:' | '::' ) !( /[\t ]+/ )? _prerequisites? ( recipe | !( /[\r\n]+/ ) ) ) 44 | 45 | _static_pattern_rule ::= >0( _targets ':' !( /[\t ]+/ )? _target_pattern ':' !( /[\t ]+/ )? _prerequisites_pattern? ( recipe | !( /[\r\n]+/ ) ) ) 46 | 47 | _targets ::= list -> targets 48 | 49 | _target_pattern ::= ( list -> pattern_list ):target 50 | 51 | _prerequisites ::= _normal_prerequisites 52 | | _normal_prerequisites? '|' _order_only_prerequisites 53 | 54 | _normal_prerequisites ::= ( list -> prerequisites ):normal 55 | 56 | _order_only_prerequisites ::= ( list -> prerequisites ):order_only 57 | 58 | _prerequisites_pattern ::= ( list -> pattern_list ):prerequisite 59 | 60 | recipe ::= >0( _attached_recipe_line !( /[\r\n]+/ ) ( conditional | _prefixed_recipe_line )* | !( /[\r\n]+/ ) ( conditional | _prefixed_recipe_line )+ ) 61 | 62 | _attached_recipe_line ::= ';' recipe_line? 63 | 64 | _prefixed_recipe_line ::= _recipeprefix recipe_line? !( /[\r\n]+/ ) 65 | 66 | recipe_line ::= ( @( 1( '@' ) ) | @( 1( '-' ) ) | @( 1( '+' ) ) )? ( shell_text_with_split -> shell_text ( _recipeprefix? shell_text_with_split -> shell_text )* _recipeprefix? )? _shell_text_without_split -> shell_text 67 | 68 | _variable_definition ::= VPATH_assignment 69 | | RECIPEPREFIX_assignment 70 | | variable_assignment 71 | | shell_assignment 72 | | define_directive 73 | 74 | VPATH_assignment ::= 'VPATH':name !( /[\t ]+/ )? ( '=' | ':=' | '::=' | '?=' | '+=' ):operator paths:value !( /[\r\n]+/ ) 75 | 76 | RECIPEPREFIX_assignment ::= '.RECIPEPREFIX':name !( /[\t ]+/ )? ( '=' | ':=' | '::=' | '?=' | '+=' ):operator text:value !( /[\r\n]+/ ) 77 | 78 | variable_assignment ::= _target_or_pattern_assignment? _name !( /[\t ]+/ )? ( '=' | ':=' | '::=' | '?=' | '+=' ):operator !( /[\t ]+/ )? ( text:value )? !( /[\r\n]+/ ) 79 | 80 | _target_or_pattern_assignment ::= list:target_or_pattern ':' !( /[\t ]+/ )? 81 | 82 | shell_assignment ::= word:name !( /[\t ]+/ )? '!=':operator !( /[\t ]+/ )? _shell_command:value !( /[\r\n]+/ ) 83 | 84 | define_directive ::= 'define' word:name !( /[\t ]+/ )? ( ( '=' | ':=' | '::=' | '?=' | '+=' ):operator )? !( /[\t ]+/ )? !( /[\r\n]+/ ) ( ( _rawline+ -> raw_text ):value )? @( 1( 'endef' ) ) !( /[\r\n]+/ ) 85 | 86 | _directive ::= include_directive 87 | | vpath_directive 88 | | export_directive 89 | | unexport_directive 90 | | override_directive 91 | | undefine_directive 92 | | private_directive 93 | | conditional 94 | 95 | include_directive ::= 'include' list:filenames !( /[\r\n]+/ ) 96 | | 'sinclude' list:filenames !( /[\r\n]+/ ) 97 | | '-include' list:filenames !( /[\r\n]+/ ) 98 | 99 | vpath_directive ::= 'vpath' !( /[\r\n]+/ ) 100 | | 'vpath' word:pattern !( /[\r\n]+/ ) 101 | | 'vpath' word:pattern paths:directories !( /[\r\n]+/ ) 102 | 103 | export_directive ::= 'export' !( /[\r\n]+/ ) 104 | | 'export' list:variables !( /[\r\n]+/ ) 105 | | 'export' variable_assignment 106 | 107 | unexport_directive ::= 'unexport' !( /[\r\n]+/ ) 108 | | 'unexport' list:variables !( /[\r\n]+/ ) 109 | 110 | override_directive ::= 'override' define_directive 111 | | 'override' variable_assignment 112 | | 'override' undefine_directive 113 | 114 | undefine_directive ::= 'undefine' word:variable !( /[\r\n]+/ ) 115 | 116 | private_directive ::= 'private' variable_assignment 117 | 118 | conditional ::= _conditional_directives:condition ( _conditional_consequence:consequence )? elsif_directive* else_directive? 'endif' !( /[\r\n]+/ ) 119 | 120 | elsif_directive ::= 'else' _conditional_directives:condition ( _conditional_consequence:consequence )? 121 | 122 | else_directive ::= 'else' !( /[\r\n]+/ ) ( _conditional_consequence:consequence )? 123 | 124 | _conditional_directives ::= ifeq_directive 125 | | ifneq_directive 126 | | ifdef_directive 127 | | ifndef_directive 128 | 129 | _conditional_consequence ::= ( _thing | _prefixed_recipe_line )+ 130 | 131 | ifeq_directive ::= 'ifeq' _conditional_args_cmp !( /[\r\n]+/ ) 132 | 133 | ifneq_directive ::= 'ifneq' _conditional_args_cmp !( /[\r\n]+/ ) 134 | 135 | ifdef_directive ::= 'ifdef' _primary:variable !( /[\r\n]+/ ) 136 | 137 | ifndef_directive ::= 'ifndef' _primary:variable !( /[\r\n]+/ ) 138 | 139 | _conditional_args_cmp ::= '(' ( _primary:arg0 )? ',' ( _primary:arg1 )? ')' 140 | | _primary:arg0 _primary:arg1 141 | 142 | _variable ::= variable_reference 143 | | substitution_reference 144 | | automatic_variable 145 | 146 | variable_reference ::= ( '$' | '$$' ) ( !( '(' ) _primary ')' | !( '{' ) _primary '}' | !( /./ ) -> word ) 147 | 148 | substitution_reference ::= ( '$' | '$$' ) ( !( '(' ) _primary:text ':' _primary:pattern '=' _primary:replacement ')' | !( '{' ) _primary:text ':' _primary:pattern '=' _primary:replacement '}' ) 149 | 150 | automatic_variable ::= ( '$' | '$$' ) ( !( 1( '@' ) ) | !( 1( '%' ) ) | !( 1( '<' ) ) | !( 1( '?' ) ) | !( 1( '^' ) ) | !( 1( '+' ) ) | !( 1( '/' ) ) | !( 1( '*' ) ) | !( '(' ) ( @( 1( '@' ) ) | @( 1( '%' ) ) | @( 1( '<' ) ) | @( 1( '?' ) ) | @( 1( '^' ) ) | @( 1( '+' ) ) | @( 1( '/' ) ) | @( 1( '*' ) ) ) ( !( 'D' ) | !( 'F' ) )? ')' | !( '{' ) ( @( 1( '@' ) ) | @( 1( '%' ) ) | @( 1( '<' ) ) | @( 1( '?' ) ) | @( 1( '^' ) ) | @( 1( '+' ) ) | @( 1( '/' ) ) | @( 1( '*' ) ) ) ( !( 'D' ) | !( 'F' ) )? '}' ) 151 | 152 | _function ::= function_call 153 | | shell_function 154 | 155 | function_call ::= ( '$' | '$$' ) !( '(' ) ( !( 'subst' ) | !( 'patsubst' ) | !( 'strip' ) | !( 'findstring' ) | !( 'filter' ) | !( 'filter-out' ) | !( 'sort' ) | !( 'word' ) | !( 'words' ) | !( 'wordlist' ) | !( 'firstword' ) | !( 'lastword' ) | !( 'dir' ) | !( 'notdir' ) | !( 'suffix' ) | !( 'basename' ) | !( 'addsuffix' ) | !( 'addprefix' ) | !( 'join' ) | !( 'wildcard' ) | !( 'realpath' ) | !( 'abspath' ) | !( 'error' ) | !( 'warning' ) | !( 'info' ) | !( 'origin' ) | !( 'flavor' ) | !( 'foreach' ) | !( 'if' ) | !( 'or' ) | !( 'and' ) | !( 'call' ) | !( 'eval' ) | !( 'file' ) | !( 'value' ) ):function !( /[\t ]+/ )? arguments ')' 156 | 157 | arguments ::= text:argument ( ',' text:argument )* 158 | 159 | shell_function ::= ( '$' | '$$' ) !( '(' ) 'shell':function !( /[\t ]+/ )? _shell_command ')' 160 | 161 | list ::= 1( _primary ( ( !( /[\t ]+/ ) | !( '\\' /\r?\n|\r/ ) -> "\\" ) _primary )* !( /[\t ]+/ )? ) 162 | 163 | paths ::= _primary ( ( !( ':' ) | !( ';' ) ) _primary )* 164 | 165 | _primary ::= word 166 | | archive 167 | | _variable 168 | | _function 169 | | concatenation 170 | | string 171 | 172 | concatenation ::= >0( _primary <0( _primary ) + ) 173 | 174 | _name ::= word:name 175 | 176 | string ::= ( '"' _string? '"' | "'" _string? "'" ):string 177 | 178 | _string ::= ( _variable | _function | @( -1( /([^'"$\r\n\\]|\\\\|\\[^\r\n])+/ ) ) )+ 179 | 180 | word ::= @( ( /[a-zA-Z0-9%\+\-\.@_\*\?\/]/ | /\\[abtnvfrE!"#\$&'\(\)\*,;<>\?\[\\\]^`{\|}~]/ | /\\[0-9]{3}/ )+ ) 181 | 182 | archive ::= word:archive !( '(' ) list:members !( ')' ) 183 | 184 | _recipeprefix ::= '\t' 185 | 186 | _rawline ::= @( /.*[\r\n]+/ ) 187 | 188 | _shell_text_without_split ::= @( ( /[^\$\r\n\\]/ | /\\[abtnvfrE!"#\$&'\(\)\*,;<>\?\[\\\]^`{\|}~]/ | /\\[0-9]{3}/ | /\\[^\n\r]/ )+ ) ( ( _variable | _function | '$$' -> escape | '//' -> escape ) @( ( /[^\$\r\n\\]/ | /\\[abtnvfrE!"#\$&'\(\)\*,;<>\?\[\\\]^`{\|}~]/ | /\\[0-9]{3}/ | /\\[^\n\r]/ )+ )? )* 189 | | ( _variable | _function | '$$' -> escape | '//' -> escape ) ( @( ( /[^\$\r\n\\]/ | /\\[abtnvfrE!"#\$&'\(\)\*,;<>\?\[\\\]^`{\|}~]/ | /\\[0-9]{3}/ | /\\[^\n\r]/ )+ )? ( _variable | _function | '$$' -> escape | '//' -> escape ) )* @( ( /[^\$\r\n\\]/ | /\\[abtnvfrE!"#\$&'\(\)\*,;<>\?\[\\\]^`{\|}~]/ | /\\[0-9]{3}/ | /\\[^\n\r]/ )+ )? 190 | 191 | shell_text_with_split ::= _shell_text_without_split !( '\\' /\r?\n|\r/ ) -> "\\" 192 | 193 | _shell_command ::= text -> shell_command 194 | 195 | text ::= @( ( /[^\$\(\)\n\r\\]/ | !( '\\' /\r?\n|\r/ ) -> "\\" | /\\[abtnvfrE!"#\$&'\(\)\*,;<>\?\[\\\]^`{\|}~]/ | /\\[0-9]{3}/ | /\\[^\n\r]/ )+ ) ( ( _variable | _function | '$$' -> escape | '//' -> escape ) @( ( /[^\$\(\)\n\r\\]/ | !( '\\' /\r?\n|\r/ ) -> "\\" | /\\[abtnvfrE!"#\$&'\(\)\*,;<>\?\[\\\]^`{\|}~]/ | /\\[0-9]{3}/ | /\\[^\n\r]/ )+ )? )* 196 | | ( _variable | _function | '$$' -> escape | '//' -> escape ) ( @( ( /[^\$\(\)\n\r\\]/ | !( '\\' /\r?\n|\r/ ) -> "\\" | /\\[abtnvfrE!"#\$&'\(\)\*,;<>\?\[\\\]^`{\|}~]/ | /\\[0-9]{3}/ | /\\[^\n\r]/ )+ )? ( _variable | _function | '$$' -> escape | '//' -> escape ) )* @( ( /[^\$\(\)\n\r\\]/ | !( '\\' /\r?\n|\r/ ) -> "\\" | /\\[abtnvfrE!"#\$&'\(\)\*,;<>\?\[\\\]^`{\|}~]/ | /\\[0-9]{3}/ | /\\[^\n\r]/ )+ )? 197 | 198 | comment ::= @( -1( /#.*/ ) ) 199 | 200 | -------------------------------------------------------------------------------- /examples/markdown.ebnf: -------------------------------------------------------------------------------- 1 | ; repository: https://github.com/ikatyang/tree-sitter-markdown.git 2 | ; commit: 8b8b77af0493e26d378135a3e7f5ae25b555b375 3 | ; json from: tree-sitter-markdown/src/grammar.json 4 | ; From /tmp/tslua/markdown0.json 5 | ; EBNF to generate grammar.js at 6 | ; https://mingodad.github.io/lua-wasm-playground/ 7 | ; based on https://github.com/eatkins/tree-sitter-ebnf-generator 8 | ; see also https://mingodad.github.io/plgh/json2ebnf.html 9 | 10 | 11 | externals ::= { 12 | _eof 13 | _lka 14 | _thm_brk_bgn 15 | _thm_brk_end_mkr 16 | _pgh_bgn_mkr 17 | _pgh_end_mkr 18 | _lnk_ref_def_end_mkr 19 | _stx_bgn_1 20 | _stx_bgn_2 21 | _stx_end_mkr 22 | _atx_bgn_1 23 | _atx_bgn_2 24 | _atx_bgn_3 25 | _atx_bgn_4 26 | _atx_bgn_5 27 | _atx_bgn_6 28 | _atx_end_mkr 29 | _ind_cod_bgn_pfx 30 | _ind_cod_bgn_mkr 31 | _ind_cod_end_mkr 32 | _fen_cod_ctn_bgn_mkr 33 | _fen_cod_bgn 34 | _fen_cod_end 35 | _fen_cod_end_mkr 36 | _htm_blk_scr_bgn_mkr 37 | _htm_blk_scr_end 38 | _htm_blk_scr_end_mkr 39 | _htm_blk_cmt_bgn_mkr 40 | _htm_blk_cmt_end 41 | _htm_blk_cmt_end_mkr 42 | _htm_blk_prc_bgn_mkr 43 | _htm_blk_prc_end 44 | _htm_blk_prc_end_mkr 45 | _htm_blk_dcl_bgn_mkr 46 | _htm_blk_dcl_end 47 | _htm_blk_dcl_end_mkr 48 | _htm_blk_cda_bgn_mkr 49 | _htm_blk_cda_end 50 | _htm_blk_cda_end_mkr 51 | _htm_blk_div_bgn_mkr 52 | _htm_blk_div_end_mkr 53 | _htm_blk_cmp_bgn_mkr 54 | _htm_blk_cmp_end_mkr 55 | _bqt_bgn 56 | _bqt_end_mkr 57 | _lst_bgn_mkr 58 | _lst_end_mkr 59 | _lst_itm_bgn 60 | _lst_itm_end_mkr 61 | _lst_itm_cnt_bgn_mkr 62 | _lst_itm_cnt_end_mkr 63 | _tbl_hed_row_bgn_mkr 64 | _tbl_dlm_row_bgn_mkr 65 | _tbl_dat_row_bgn_mkr 66 | _tbl_row_end_mkr 67 | _bsl_esc 68 | _chr_ref 69 | _emp_bgn 70 | _emp_end 71 | _stg_bgn 72 | _stg_end 73 | _del_bgn 74 | _del_end 75 | _img_bgn 76 | _lnk_bgn 77 | _lnk_end 78 | _lnk_ref_def_bgn 79 | _lnk_ref_def_cln 80 | _lnk_inl_bgn 81 | _lnk_inl_end 82 | _lnk_dst_bgn 83 | _lnk_dst_end 84 | _lnk_dst_bgn_mkr 85 | _lnk_dst_end_mkr 86 | _lnk_tit_bgn 87 | _lnk_tit_end 88 | _lnk_ref_bgn 89 | _lnk_ref_end 90 | _ext_www_aut_lnk_bgn_mkr 91 | _ext_url_aut_lnk_bgn_mkr 92 | _ext_eml_aut_lnk_bgn_mkr 93 | _ext_aut_lnk_end_mkr 94 | _uri_aut_lnk_bgn 95 | _eml_aut_lnk_bgn 96 | _aut_lnk_end 97 | _cod_spn_bgn 98 | _cod_spn_end 99 | _htm_opn_tag_bgn 100 | _htm_tag_end 101 | _htm_cls_tag_bgn 102 | _htm_slf_tag_end 103 | _htm_dcl_bgn 104 | _htm_atr_eql 105 | _htm_atr_val_bgn 106 | _htm_atr_val_end 107 | _htm_atr_val_bgn_mkr 108 | _htm_atr_val_end_mkr 109 | _htm_cmt_bgn 110 | _htm_cmt_end 111 | _htm_prc_bgn 112 | _htm_prc_end 113 | _htm_cda_bgn 114 | _htm_cda_end 115 | _atx_end 116 | _lst_chk_box 117 | _tbl_col_sep 118 | _tbl_col_aln 119 | _fen_cod_inf_bgn_mkr 120 | _fen_cod_inf_end_mkr 121 | _hrd_lbk 122 | _sft_lbk 123 | _blk_lbk 124 | _bnk_lbk 125 | _lit_lbk 126 | _wsp 127 | _txt_frg 128 | _wrd 129 | _vtr_spc 130 | } 131 | 132 | extras ::= { 133 | _lka 134 | _lit_lbk 135 | _wsp 136 | } 137 | 138 | conflicts ::= { 139 | { _chk_box_pgh_ctn _chk_box_lik_stx_ctn } 140 | { _fen_cod_ctn } 141 | } 142 | 143 | rules: 144 | 145 | document ::= ( _blk_nod | _bnk_lbk )* _eof 146 | 147 | _blk_nod ::= _thm_brk 148 | | _pgh 149 | | _lnk_ref_def 150 | | _stx 151 | | _atx 152 | | _ind_cod 153 | | _fen_cod 154 | | _htm_blk_scr 155 | | _htm_blk_cmt 156 | | _htm_blk_prc 157 | | _htm_blk_dcl 158 | | _htm_blk_cda 159 | | _htm_blk_div 160 | | _htm_blk_cmp 161 | | _bqt 162 | | _tig_lst 163 | | _los_lst 164 | | _tbl -> table 165 | 166 | _thm_brk ::= _thm_brk_hed -> thematic_break _thm_brk_end_mkr 167 | 168 | _thm_brk_hed ::= _thm_brk_bgn 169 | 170 | _pgh ::= _pgh_hed -> paragraph _pgh_end_mkr 171 | 172 | _pgh_hed ::= _pgh_bgn_mkr ( _inl_nod | _inl_lbk )* 173 | 174 | _lnk_ref_def ::= _lnk_ref_def_hed -> link_reference_definition _lnk_ref_def_end_mkr 175 | 176 | _lnk_ref_def_hed ::= _pgh_bgn_mkr _lnk_ref_def_bgn ( _txt -> text | _bsl_esc -> backslash_escape )* -> link_label _lnk_end _lnk_ref_def_cln _lnk_dst -> link_destination ( _lnk_tit -> link_title )? 177 | 178 | _stx ::= _stx_hed -> setext_heading _stx_end_mkr 179 | 180 | _stx_bgn ::= _stx_bgn_1 -> setext_h1_underline 181 | | _stx_bgn_2 -> setext_h2_underline 182 | 183 | _stx_hed ::= _pgh_hed -> heading_content _pgh_end_mkr _stx_bgn 184 | 185 | _atx ::= _atx_hed -> atx_heading _atx_end_mkr 186 | 187 | _atx_bgn ::= _atx_bgn_1 -> atx_h1_marker 188 | | _atx_bgn_2 -> atx_h2_marker 189 | | _atx_bgn_3 -> atx_h3_marker 190 | | _atx_bgn_4 -> atx_h4_marker 191 | | _atx_bgn_5 -> atx_h5_marker 192 | | _atx_bgn_6 -> atx_h6_marker 193 | 194 | _atx_hed ::= _atx_bgn _inl_nod* -> heading_content _atx_end? 195 | 196 | _ind_cod ::= _ind_cod_bgn_pfx _ind_cod_hed -> indented_code_block _ind_cod_end_mkr 197 | 198 | _ind_cod_hed ::= _ind_cod_bgn_mkr ( _vtr_spc -> virtual_space | _txt -> text | _blk_lbk -> line_break )* 199 | 200 | _fen_cod ::= _fen_cod_hed -> fenced_code_block _fen_cod_end_mkr 201 | 202 | _fen_cod_hed ::= _fen_cod_bgn _fen_cod_inf? ( _blk_lbk ( _fen_cod_ctn -> code_fence_content )? )? ( _blk_lbk _fen_cod_end )? 203 | 204 | _fen_cod_inf ::= _fen_cod_inf_bgn_mkr ( _inl_txt )* -> info_string _fen_cod_inf_end_mkr 205 | 206 | _fen_cod_ctn ::= _fen_cod_ctn_bgn_mkr ( _vtr_spc -> virtual_space | _txt -> text | _blk_lbk -> line_break )* 207 | 208 | _htm_blk_scr ::= _htm_blk_scr_hed -> html_block _htm_blk_scr_end_mkr 209 | 210 | _htm_blk_scr_hed ::= _htm_blk_scr_bgn_mkr ( _vtr_spc -> virtual_space | _txt -> text | _blk_lbk -> line_break )* _htm_blk_scr_end? 211 | 212 | _htm_blk_cmt ::= _htm_blk_cmt_hed -> html_block _htm_blk_cmt_end_mkr 213 | 214 | _htm_blk_cmt_hed ::= _htm_blk_cmt_bgn_mkr ( _vtr_spc -> virtual_space | _txt -> text | _blk_lbk -> line_break )* _htm_blk_cmt_end? 215 | 216 | _htm_blk_prc ::= _htm_blk_prc_hed -> html_block _htm_blk_prc_end_mkr 217 | 218 | _htm_blk_prc_hed ::= _htm_blk_prc_bgn_mkr ( _vtr_spc -> virtual_space | _txt -> text | _blk_lbk -> line_break )* _htm_blk_prc_end? 219 | 220 | _htm_blk_dcl ::= _htm_blk_dcl_hed -> html_block _htm_blk_dcl_end_mkr 221 | 222 | _htm_blk_dcl_hed ::= _htm_blk_dcl_bgn_mkr ( _vtr_spc -> virtual_space | _txt -> text | _blk_lbk -> line_break )* _htm_blk_dcl_end? 223 | 224 | _htm_blk_cda ::= _htm_blk_cda_hed -> html_block _htm_blk_cda_end_mkr 225 | 226 | _htm_blk_cda_hed ::= _htm_blk_cda_bgn_mkr ( _vtr_spc -> virtual_space | _txt -> text | _blk_lbk -> line_break )* _htm_blk_cda_end? 227 | 228 | _htm_blk_div ::= _htm_blk_div_hed -> html_block _htm_blk_div_end_mkr 229 | 230 | _htm_blk_div_hed ::= _htm_blk_div_bgn_mkr ( _vtr_spc -> virtual_space | _txt -> text | _blk_lbk -> line_break )* 231 | 232 | _htm_blk_cmp ::= _htm_blk_cmp_hed -> html_block _htm_blk_cmp_end_mkr 233 | 234 | _htm_blk_cmp_hed ::= _htm_blk_cmp_bgn_mkr ( _vtr_spc -> virtual_space | _txt -> text | _blk_lbk -> line_break )* 235 | 236 | _bqt ::= _bqt_hed -> block_quote _bqt_end_mkr 237 | 238 | _bqt_hed ::= _bqt_bgn ( _blk_nod | _bnk_lbk )* 239 | 240 | _tig_lst ::= _tig_lst_hed -> tight_list _lst_end_mkr 241 | 242 | _tig_lst_hed ::= _lst_bgn_mkr _tig_lst_itm* 243 | 244 | _los_lst ::= _los_lst_hed -> loose_list _lst_end_mkr 245 | 246 | _los_lst_hed ::= _lst_bgn_mkr _tig_lst_itm* ( _bnk_lbk | _los_lst_itm ) ( _tig_lst_itm | _los_lst_itm | _bnk_lbk )* 247 | 248 | _tig_lst_itm ::= ( _tig_lst_itm_hed -> list_item | _tig_chk_box_lst_itm_hed -> task_list_item ) _lst_itm_cnt_end_mkr _lst_itm_end_mkr 249 | 250 | _tig_lst_itm_hed ::= _lst_itm_bgn -> list_marker _lst_itm_cnt_bgn_mkr _chk_box_lik_stx? _blk_nod* 251 | 252 | _tig_chk_box_lst_itm_hed ::= _lst_itm_bgn -> list_marker _lst_itm_cnt_bgn_mkr _chk_box_pgh _blk_nod* 253 | 254 | _los_lst_itm ::= ( _los_lst_itm_hed -> list_item | _los_chk_box_lst_itm_hed -> task_list_item ) _lst_itm_cnt_end_mkr _lst_itm_end_mkr 255 | 256 | _los_lst_itm_hed ::= _lst_itm_bgn -> list_marker _lst_itm_cnt_bgn_mkr _chk_box_lik_stx? _blk_nod* _bnk_lbk ( _bnk_lbk | _blk_nod )* 257 | 258 | _los_chk_box_lst_itm_hed ::= _lst_itm_bgn -> list_marker _lst_itm_cnt_bgn_mkr _chk_box_pgh _blk_nod* _bnk_lbk ( _bnk_lbk | _blk_nod )* 259 | 260 | _chk_box_pgh ::= _pgh_bgn_mkr _chk_box_pgh_ctn -> paragraph _pgh_end_mkr 261 | 262 | _chk_box_pgh_ctn ::= _lst_chk_box -> task_list_item_marker ( _inl_nod | _inl_lbk )* 263 | 264 | _chk_box_lik_stx ::= _chk_box_lik_stx_hed -> setext_heading _stx_end_mkr 265 | 266 | _chk_box_lik_stx_hed ::= _pgh_bgn_mkr _chk_box_lik_stx_ctn -> heading_content _pgh_end_mkr _stx_bgn 267 | 268 | _chk_box_lik_stx_ctn ::= _lst_chk_box ( _inl_nod | _inl_lbk )* 269 | 270 | _tbl ::= _tbl_hed_row _tbl_dlm_row _tbl_dat_row* 271 | 272 | _tbl_hed_row ::= _tbl_hed_row_hed -> table_header_row _tbl_row_end_mkr 273 | 274 | _tbl_hed_row_hed ::= _tbl_hed_row_bgn_mkr _tbl_col_sep? _tbl_dat_cel -> table_cell ( _tbl_col_sep _tbl_dat_cel -> table_cell )* _tbl_col_sep? 275 | 276 | _tbl_dlm_row ::= _tbl_dlm_row_hed -> table_delimiter_row _tbl_row_end_mkr 277 | 278 | _tbl_dlm_row_hed ::= _tbl_dlm_row_bgn_mkr _tbl_col_sep? _tbl_col_aln -> table_column_alignment ( _tbl_col_sep _tbl_col_aln -> table_column_alignment )* _tbl_col_sep? 279 | 280 | _tbl_dat_row ::= _tbl_dat_row_hed -> table_data_row _tbl_row_end_mkr 281 | 282 | _tbl_dat_row_hed ::= _tbl_dat_row_bgn_mkr _tbl_col_sep? _tbl_dat_cel -> table_cell ( _tbl_col_sep _tbl_dat_cel -> table_cell )* _tbl_col_sep? 283 | 284 | _tbl_dat_cel ::= _inl_nod+ 285 | 286 | _inl_nod ::= _inl_txt 287 | | _emp -> emphasis 288 | | _stg -> strong_emphasis 289 | | _del -> strikethrough 290 | | _lnk -> link 291 | | _img -> image 292 | | _ext_www_aut_lnk -> www_autolink 293 | | _ext_url_aut_lnk -> uri_autolink 294 | | _ext_eml_aut_lnk -> email_autolink 295 | | _uri_aut_lnk -> uri_autolink 296 | | _eml_aut_lnk -> email_autolink 297 | | _cod_spn -> code_span 298 | | _htm_opn_tag -> html_open_tag 299 | | _htm_slf_cls_tag -> html_self_closing_tag 300 | | _htm_cls_tag -> html_close_tag 301 | | _htm_cmt -> html_comment 302 | | _htm_prc -> html_processing_instruction 303 | | _htm_dcl -> html_declaration 304 | | _htm_cda -> html_cdata_section 305 | 306 | _inl_txt ::= _txt -> text 307 | | _bsl_esc -> backslash_escape 308 | | _chr_ref -> character_reference 309 | 310 | _inl_lbk ::= _sft_lbk -> soft_line_break 311 | | _hrd_lbk -> hard_line_break 312 | 313 | _emp ::= _emp_bgn ( _inl_nod | _inl_lbk )* _emp_end 314 | 315 | _stg ::= _stg_bgn ( _inl_nod | _inl_lbk )* _stg_end 316 | 317 | _del ::= _del_bgn ( _inl_nod | _inl_lbk )* _del_end 318 | 319 | _lnk ::= _lnk_bgn ( _inl_nod | _inl_lbk )* -> link_text _lnk_tal 320 | 321 | _img ::= _img_bgn ( _inl_nod | _inl_lbk )* -> image_description _lnk_tal 322 | 323 | _lnk_tal ::= _lnk_end ( _lnk_tal_inl | _lnk_tal_ful | _lnk_tal_clp )? 324 | 325 | _lnk_tal_inl ::= _lnk_inl_bgn ( _lnk_dst -> link_destination ( _lnk_tit -> link_title )? )? _lnk_inl_end 326 | 327 | _lnk_tal_ful ::= _lnk_ref_bgn ( _txt -> text | _bsl_esc -> backslash_escape )+ -> link_label _lnk_ref_end 328 | 329 | _lnk_tal_clp ::= _lnk_ref_bgn _lnk_ref_end 330 | 331 | _lnk_dst ::= _lnk_dst_bgn _inl_txt* _lnk_dst_end 332 | | _lnk_dst_bgn_mkr _inl_txt* _lnk_dst_end_mkr 333 | 334 | _lnk_tit ::= _lnk_tit_bgn _inl_txt* _lnk_tit_end 335 | 336 | _ext_www_aut_lnk ::= _ext_www_aut_lnk_hed _ext_aut_lnk_end_mkr 337 | 338 | _ext_www_aut_lnk_hed ::= _ext_www_aut_lnk_bgn_mkr ( _txt -> text | _bsl_esc -> backslash_escape )* 339 | 340 | _ext_url_aut_lnk ::= _ext_url_aut_lnk_hed _ext_aut_lnk_end_mkr 341 | 342 | _ext_url_aut_lnk_hed ::= _ext_url_aut_lnk_bgn_mkr ( _txt -> text | _bsl_esc -> backslash_escape )* 343 | 344 | _ext_eml_aut_lnk ::= _ext_eml_aut_lnk_hed _ext_aut_lnk_end_mkr 345 | 346 | _ext_eml_aut_lnk_hed ::= _ext_eml_aut_lnk_bgn_mkr ( _txt -> text | _bsl_esc -> backslash_escape )* 347 | 348 | _uri_aut_lnk ::= _uri_aut_lnk_bgn ( _txt -> text | _bsl_esc -> backslash_escape )* _aut_lnk_end 349 | 350 | _eml_aut_lnk ::= _eml_aut_lnk_bgn ( _txt -> text | _bsl_esc -> backslash_escape )* _aut_lnk_end 351 | 352 | _cod_spn ::= _cod_spn_bgn ( _txt -> text | _bsl_esc -> backslash_escape )* _cod_spn_end 353 | 354 | _htm_opn_tag ::= _htm_opn_tag_hed _htm_tag_end 355 | 356 | _htm_slf_cls_tag ::= _htm_opn_tag_hed _htm_slf_tag_end 357 | 358 | _htm_opn_tag_hed ::= _htm_opn_tag_bgn _wrd -> html_tag_name ( _htm_atr -> html_atrribute )* 359 | 360 | _htm_cls_tag ::= _htm_cls_tag_bgn _wrd -> html_tag_name _htm_tag_end 361 | 362 | _htm_cmt ::= _htm_cmt_bgn ( _txt -> text | _bsl_esc -> backslash_escape )* _htm_cmt_end 363 | 364 | _htm_prc ::= _htm_prc_bgn ( _txt -> text | _bsl_esc -> backslash_escape )* _htm_prc_end 365 | 366 | _htm_dcl ::= _htm_dcl_bgn _wrd -> html_declaration_name ( _txt -> text | _bsl_esc -> backslash_escape )* _htm_tag_end 367 | 368 | _htm_cda ::= _htm_cda_bgn ( _txt -> text | _bsl_esc -> backslash_escape )* _htm_cda_end 369 | 370 | _htm_atr ::= _wrd -> html_attribute_key ( _htm_atr_eql _htm_atr_val -> html_attribute_value )? 371 | 372 | _htm_atr_val ::= _htm_atr_val_bgn ( _txt -> text | _bsl_esc -> backslash_escape )* _htm_atr_val_end 373 | | _htm_atr_val_bgn_mkr ( _txt -> text | _bsl_esc -> backslash_escape )* _htm_atr_val_end_mkr 374 | 375 | _txt ::= >0( _txt_frg+ ) 376 | 377 | -------------------------------------------------------------------------------- /examples/minizinc.ebnf: -------------------------------------------------------------------------------- 1 | ; repository: https://github.com/Dekker1/tree-sitter-minizinc.git 2 | ; commit: e4af426f3c0e26c9bc1f85a54d84ee855046d267 3 | ; json from: tree-sitter-minizinc/src/grammar.json 4 | ; From /tmp/tslua/minizinc0.json 5 | ; EBNF to generate grammar.js at 6 | ; https://mingodad.github.io/lua-wasm-playground/ 7 | ; based on https://github.com/eatkins/tree-sitter-ebnf-generator 8 | ; see also https://mingodad.github.io/plgh/json2ebnf.html 9 | 10 | 11 | extras ::= { 12 | /\s/ 13 | line_comment 14 | block_comment 15 | } 16 | 17 | supertypes ::= { 18 | _expression 19 | _item 20 | _type 21 | } 22 | 23 | conflicts ::= { 24 | { _expression generator } 25 | { _expression assignment } 26 | } 27 | 28 | word ::= identifier 29 | 30 | rules: 31 | 32 | source_file ::= ( _item ';' )* _item? 33 | 34 | _item ::= annotation 35 | | assignment 36 | | constraint 37 | | declaration 38 | | enumeration 39 | | function_item 40 | | goal 41 | | include 42 | | output 43 | | predicate 44 | 45 | annotation ::= 'annotation' identifier:name ( _parameters:parameters )? ( '=' _expression:expr )? 46 | 47 | assignment ::= identifier:name '=' _expression:expr 48 | 49 | constraint ::= 'constraint' _expression 50 | 51 | declaration ::= _type:type ':' identifier:name ( _annotations:annotations )? ( '=' _expression:expr )? 52 | 53 | enumeration ::= 'enum' identifier:name ( _annotations:annotations )? ( '=' '{' ( ( identifier ',' )* identifier? ):members '}' )? 54 | 55 | function_item ::= 'function' _type:type ':' identifier:name _parameters:parameters ( _annotations:annotations )? ( '=' _expression:expr )? 56 | 57 | goal ::= 'solve' ( 'satisfy' | 'maximize' _expression | 'minimize' _expression ):strategy 58 | 59 | include ::= 'include' string_literal 60 | 61 | output ::= 'output' _expression 62 | 63 | predicate ::= ( 'predicate' | 'test' ):type identifier:name _parameters:parameters ( _annotations:annotations )? ( '=' _expression:expr )? 64 | 65 | _annotations ::= ( '::' _expression )+ 66 | 67 | _parameters ::= '(' ( _type ( ':' identifier )? ',' )* ( _type ( ':' identifier )? )? ')' 68 | 69 | _expression ::= identifier 70 | | _literal 71 | | array_comprehension 72 | | call 73 | | generator_call 74 | | if_then_else 75 | | indexed_access 76 | | infix_operator 77 | | let_expression 78 | | prefix_operator 79 | | set_comprehension 80 | | string_interpolation 81 | | parenthesised_expression 82 | 83 | parenthesised_expression ::= '(' _expression ')' 84 | 85 | array_comprehension ::= '[' _expression '|' generator ( ',' generator )* ','? ']' 86 | 87 | call ::= 15( identifier:name '(' ( ( _expression ',' )* _expression? ):arguments ')' ) 88 | 89 | generator_call ::= 15( identifier:name '(' ( generator ( ',' generator )* ','? ):generators ')' '(' _expression:template ')' ) 90 | 91 | generator ::= identifier 'in' _expression ( 'where' _expression )? 92 | 93 | if_then_else ::= 'if' _expression 'then' _expression ( 'elseif' _expression 'then' _expression )* ( 'else' _expression )? 'endif' 94 | 95 | indexed_access ::= 15( _expression:collection '[' ( _expression ( ',' _expression )* ):indices ']' ) 96 | 97 | infix_operator ::= <1( _expression:left '<->':operator _expression:right ) 98 | | <2( _expression:left ( '->' | '<-' ):operator _expression:right ) 99 | | <1( _expression:left '\\/':operator _expression:right ) 100 | | <2( _expression:left 'xor':operator _expression:right ) 101 | | <3( _expression:left '/\\':operator _expression:right ) 102 | | <4( _expression:left ( '=' | '==' | '!=' | '<' | '<=' | '>' | '>=' | 'in' | 'subset' | 'superset' ):operator _expression:right ) 103 | | <5( _expression:left 'union':operator _expression:right ) 104 | | <6( _expression:left 'diff':operator _expression:right ) 105 | | <7( _expression:left 'symdiff':operator _expression:right ) 106 | | <9( _expression:left 'intersect':operator _expression:right ) 107 | | <8( _expression:left '..':operator _expression:right ) 108 | | <10( _expression:left ( '+' | '-' | '++' ):operator _expression:right ) 109 | | <11( _expression:left ( '*' | '/' | 'div' | 'mod' ):operator _expression:right ) 110 | | <12( _expression:left '^':operator _expression:right ) 111 | | <14( _expression:left '::':operator _expression:right ) 112 | 113 | let_expression ::= 'let' '{' ( ( ( declaration | constraint ) ( ',' | ';' ) )* ( declaration | constraint )? ):let '}' 'in' _expression:in 114 | 115 | prefix_operator ::= 13( ( '-' | 'not' | '¬' ):operator _expression ) 116 | 117 | set_comprehension ::= '{' _expression '|' generator ( ',' generator )* ','? '}' 118 | 119 | string_interpolation ::= '"' string_content? ( '\\(' _expression ')' string_content? )+ '"' 120 | 121 | _type ::= array_type 122 | | type_base 123 | 124 | array_type ::= 'array' '[' type_base ( ',' type_base )* ','? ']' 'of' _type 125 | 126 | type_base ::= ( ( 'var' | 'par' ):var_par )? ( 'opt':opt )? ( ( 'set' 'of' ):set )? ( primitive_type | _expression ) 127 | 128 | primitive_type ::= 'ann' 129 | | 'bool' 130 | | 'float' 131 | | 'int' 132 | | 'string' 133 | 134 | _literal ::= absent 135 | | array_literal 136 | | boolean_literal 137 | | float_literal 138 | | integer_literal 139 | | set_literal 140 | | string_literal 141 | 142 | absent ::= '<>' 143 | 144 | array_literal ::= '[' ( _expression ',' )* _expression? ']' 145 | 146 | boolean_literal ::= 'true' 147 | | 'false' 148 | 149 | float_literal ::= @( /\d+\.\d+/ | /\d+(\.\d+)?[Ee][+-]?\d+/ ) 150 | 151 | integer_literal ::= @( /[0-9]+/ | /0x[0-9a-fA-F]+/ | /0b[01]+/ | /0o[0-7]+/ ) 152 | 153 | set_literal ::= '{' ( _expression ',' )* _expression? '}' 154 | 155 | string_literal ::= '"' string_content? -> "content" '"' 156 | 157 | string_content ::= ( !( 1( /[^"\n\\]+/ ) ) | escape_sequence )+ 158 | 159 | escape_sequence ::= !( '\\' ( /[^xuU]/ | /\d{2,3}/ | /x[0-9a-fA-F]{2,}/ | /u[0-9a-fA-F]{4}/ | /U[0-9a-fA-F]{8}/ ) ) 160 | 161 | identifier ::= /[A-Za-z][A-Za-z0-9_]*/ 162 | 163 | line_comment ::= @( '%' /.*/ ) 164 | 165 | block_comment ::= @( '/*' /([^*]|\*[^\/]|\n)*?\*?/ '*/' ) 166 | 167 | -------------------------------------------------------------------------------- /examples/regex.ebnf: -------------------------------------------------------------------------------- 1 | ; repository: https://github.com/tree-sitter/tree-sitter-regex.git 2 | ; commit: f70251e1f1d72bd6dc1f897f956f9112f8668441 3 | ; json from: tree-sitter-regex/src/grammar.json 4 | ; From /tmp/tslua/regex0.json 5 | ; EBNF to generate grammar.js at 6 | ; https://mingodad.github.io/lua-wasm-playground/ 7 | ; based on https://github.com/eatkins/tree-sitter-ebnf-generator 8 | ; see also https://mingodad.github.io/plgh/json2ebnf.html 9 | 10 | 11 | extras ::= { 12 | /\r?\n/ 13 | } 14 | 15 | inline ::= { 16 | _character_escape 17 | _class_atom 18 | } 19 | 20 | conflicts ::= { 21 | { character_class class_range } 22 | } 23 | 24 | rules: 25 | 26 | pattern ::= alternation 27 | | term 28 | 29 | alternation ::= term? ( '|' term? )+ 30 | 31 | term ::= ( ( start_assertion | end_assertion | boundary_assertion | non_boundary_assertion | lookaround_assertion | pattern_character | character_class | any_character | decimal_escape | character_class_escape | _character_escape | backreference_escape | anonymous_capturing_group | named_capturing_group | non_capturing_group ) ( zero_or_more | one_or_more | optional | count_quantifier )? )+ 32 | 33 | any_character ::= '.' 34 | 35 | start_assertion ::= '^' 36 | 37 | end_assertion ::= '$' 38 | 39 | boundary_assertion ::= '\\b' 40 | 41 | non_boundary_assertion ::= '\\B' 42 | 43 | lookaround_assertion ::= _lookahead_assertion 44 | | _lookbehind_assertion 45 | 46 | _lookahead_assertion ::= '(?' ( '=' | '!' ) pattern ')' 47 | 48 | _lookbehind_assertion ::= '(?<' ( '=' | '!' ) pattern ')' 49 | 50 | pattern_character ::= /[^\^\$\\\.\*\+\?\(\)\[\]\|\r?\n]/ 51 | 52 | character_class ::= '[' '^'? ( class_range | _class_atom )* ']' 53 | 54 | class_range ::= >0( _class_atom '-' _class_atom ) 55 | 56 | _class_atom ::= '-' -> class_character 57 | | class_character 58 | | '\\-' -> identity_escape 59 | | character_class_escape 60 | | _character_escape 61 | 62 | class_character ::= /[^\\\]\-]/ 63 | 64 | anonymous_capturing_group ::= '(' pattern ')' 65 | 66 | named_capturing_group ::= '(?<' group_name '>' pattern ')' 67 | 68 | non_capturing_group ::= '(?:' pattern ')' 69 | 70 | zero_or_more ::= '*' ( '?' -> lazy )? 71 | 72 | one_or_more ::= '+' ( '?' -> lazy )? 73 | 74 | optional ::= '?' ( '?' -> lazy )? 75 | 76 | count_quantifier ::= '{' decimal_digits ( ',' decimal_digits )? '}' ( '?' -> lazy )? 77 | 78 | backreference_escape ::= '\\k' group_name 79 | 80 | decimal_escape ::= /\\[1-9][0-9]*/ 81 | 82 | character_class_escape ::= /\\[dDsSwW]/ 83 | | /\\[pP]/ '{' unicode_property_value_expression '}' 84 | 85 | unicode_property_value_expression ::= ( unicode_property -> unicode_property_name '=' )? unicode_property -> unicode_property_value 86 | 87 | unicode_property ::= /[a-zA-Z_0-9]+/ 88 | 89 | _character_escape ::= control_escape 90 | | control_letter_escape 91 | | identity_escape 92 | 93 | control_escape ::= /\\[bfnrtv0]/ 94 | 95 | control_letter_escape ::= /\\c[a-zA-Z]/ 96 | 97 | identity_escape ::= @( '\\' /[^kdDsSpPwWbfnrtv0-9]/ ) 98 | 99 | group_name ::= /[A-Za-z0-9]+/ 100 | 101 | decimal_digits ::= /\d+/ 102 | 103 | -------------------------------------------------------------------------------- /examples/sample.json.txt: -------------------------------------------------------------------------------- 1 | [{ 2 | "string": "some\ntext", 3 | "boolean": true, 4 | "number": -1.5e+2, 5 | "null": null 6 | }] 7 | -------------------------------------------------------------------------------- /examples/simple.lua: -------------------------------------------------------------------------------- 1 | -- This is a simple Lua script to show the playground functionality 2 | -- The content of 'Input Text (arg[1])' is available as 'arg[1]' 3 | -- If there is any error they will be shown at the bottom of the screen and we can click on then 4 | -- The output is shown on 'Output' 5 | 6 | local input_text = arg[1] 7 | 8 | print("Here is the content of 'Input Text (arg[1])'") 9 | print(input_text) 10 | 11 | -- There is two embedded files that can be viewed as shown bellow 12 | local lpegrex = io.open('lpegrex.lua'):read("a*") 13 | print(lpegrex) 14 | 15 | local relabel = io.open('relabel.lua'):read("a*") 16 | print(relabel) -------------------------------------------------------------------------------- /examples/squirrel.ebnf: -------------------------------------------------------------------------------- 1 | ; repository: https://github.com/tree-sitter-grammars/tree-sitter-squirrel.git 2 | ; commit: 072c969749e66f000dba35a33c387650e203e96e 3 | ; json from: tree-sitter-squirrel/src/grammar.json 4 | ; From /tmp/tslua/squirrel0.json 5 | ; EBNF to generate grammar.js at 6 | ; https://mingodad.github.io/lua-wasm-playground/ 7 | ; based on https://github.com/eatkins/tree-sitter-ebnf-generator 8 | ; see also https://mingodad.github.io/plgh/json2ebnf.html 9 | 10 | 11 | externals ::= { 12 | verbatim_string 13 | } 14 | 15 | extras ::= { 16 | comment 17 | /\s/ 18 | } 19 | 20 | supertypes ::= { 21 | expression 22 | primary_expression 23 | } 24 | 25 | inline ::= { 26 | expression_statement 27 | _statements 28 | _statement 29 | } 30 | 31 | word ::= identifier 32 | 33 | rules: 34 | 35 | script ::= _statements 36 | 37 | _statements ::= _statement+ 38 | 39 | _statement ::= block 40 | | if_statement 41 | | while_statement 42 | | do_while_statement 43 | | switch_statement 44 | | for_statement 45 | | foreach_statement 46 | | break 47 | | continue 48 | | return 49 | | yield 50 | | local_declaration 51 | | var_statement 52 | | function_declaration 53 | | class_declaration 54 | | try_statement 55 | | throw_statement 56 | | const_declaration 57 | | enum_declaration 58 | | expression_statement 59 | 60 | expression_statement ::= >0( expression ';'? | ';' ) 61 | 62 | block ::= '{' _statement* '}' 63 | 64 | if_statement ::= >1( 'if' parenthesized_expression:condition _statement:consequence else_statement? ) 65 | 66 | else_statement ::= >1( 'else' _statement:alternative ) 67 | 68 | while_statement ::= >0( 'while' '(' expression ')' _statement? ) 69 | 70 | do_while_statement ::= >0( 'do' _statement 'while' '(' expression ')' ) 71 | 72 | switch_statement ::= 'switch' '(' expression ')' '{' case_statement* default_statement? '}' 73 | 74 | case_statement ::= 'case' expression:case ':' _statement* 75 | 76 | default_statement ::= 'default' ':' _statement* 77 | 78 | for_statement ::= 'for' '(' ( expression | local_declaration )?:initial ';' expression?:condition ';' expression?:increment ')' _statement 79 | 80 | foreach_statement ::= 'foreach' '(' ( identifier:index ',' )? identifier:value 'in' expression:collection ')' _statement 81 | 82 | break ::= 'break' ';' 83 | 84 | continue ::= 'continue' ';' 85 | 86 | return ::= >0( 'return' ( expression | table )? ';'? ) 87 | 88 | yield ::= 'yield' expression? ( ';' | '\n' ) 89 | 90 | resume_expression ::= 'resume' expression 91 | 92 | local_declaration ::= <0( 'local' _initz ';'? ) 93 | 94 | _initz ::= >0( identifier ( ( '=' | '<-' ) ( expression | table ) )? ( ',' _initz )? ) 95 | 96 | function_declaration ::= 'function' identifier ( '::' identifier )* '(' parameters? ')' _statement 97 | 98 | parameters ::= parameter ( ',' parameter )* 99 | 100 | parameter ::= identifier ( '=' const_value )? 101 | | '...' 102 | 103 | class_declaration ::= 'class' identifier ( '.' identifier )* ( 'extends' identifier )? attribute_declaration? '{' member_declaration* '}' 104 | 105 | member_declaration ::= attribute_declaration? ( 'static'? identifier '=' ( expression | table ) ';'? | '[' expression ']' '=' expression ';'? | function_declaration | 'constructor' '(' parameters? ')' _statement ) 106 | 107 | try_statement ::= 'try' _statement catch_statement 108 | 109 | catch_statement ::= 'catch' '(' identifier ')' _statement 110 | 111 | throw_statement ::= >0( 'throw' expression ';'? ) 112 | 113 | const_declaration ::= 'const' identifier '=' const_value ( ';' | '\n' ) 114 | 115 | const_value ::= array 116 | | table 117 | | integer 118 | | float 119 | | string 120 | | verbatim_string 121 | | char 122 | | bool 123 | | null 124 | | call_expression 125 | | identifier 126 | | global_variable 127 | 128 | enum_declaration ::= >0( 'enum' identifier attribute_declaration? '{' identifier ( '=' const_value )? ( ',' identifier ( '=' const_value )? )* '}' ';'? ) 129 | 130 | attribute_declaration ::= '' 131 | 132 | expression ::= delete_expression 133 | | clone_expression 134 | | array 135 | | assignment_expression 136 | | update_expression 137 | | resume_expression 138 | | primary_expression 139 | 140 | primary_expression ::= >0( unary_expression | binary_expression | ternary_expression | anonymous_function | deref_expression | index_expression | call_expression | lambda_expression | parenthesized_expression | integer | float | string | verbatim_string | char | bool | null | identifier | global_variable ) 141 | 142 | unary_expression ::= <13( ( '-' | '~' | '!' | 'typeof' | '++' | '--' ):operator ( expression | table ):operand ';'? | expression:operand ( '++' | '--' ):operator ';'? ) 143 | 144 | binary_expression ::= <11( expression:left '+':operator expression:right ';'? ) 145 | | <11( expression:left '-':operator expression:right ';'? ) 146 | | <12( expression:left '*':operator expression:right ';'? ) 147 | | <12( expression:left '/':operator expression:right ';'? ) 148 | | <12( expression:left '%':operator expression:right ';'? ) 149 | | <3( expression:left '||':operator expression:right ';'? ) 150 | | <4( expression:left '&&':operator expression:right ';'? ) 151 | | <4( expression:left 'in':operator expression:right ';'? ) 152 | | <5( expression:left '|':operator expression:right ';'? ) 153 | | <6( expression:left '^':operator expression:right ';'? ) 154 | | <7( expression:left '&':operator expression:right ';'? ) 155 | | <8( expression:left '==':operator expression:right ';'? ) 156 | | <8( expression:left '!=':operator expression:right ';'? ) 157 | | <9( expression:left '<=>':operator expression:right ';'? ) 158 | | <9( expression:left '>':operator expression:right ';'? ) 159 | | <9( expression:left '>=':operator expression:right ';'? ) 160 | | <9( expression:left '<=':operator expression:right ';'? ) 161 | | <9( expression:left '<':operator expression:right ';'? ) 162 | | <9( expression:left 'instanceof':operator expression:right ';'? ) 163 | | <10( expression:left '<<':operator expression:right ';'? ) 164 | | <10( expression:left '>>':operator expression:right ';'? ) 165 | | <10( expression:left '>>>':operator expression:right ';'? ) 166 | 167 | ternary_expression ::= >2( expression:condition '?' ( expression | table ):consequence ':' ( expression | table ):alternative ) 168 | 169 | assignment_expression ::= >1( expression:left '=':operator ( expression | table ):right ) 170 | 171 | update_expression ::= >1( expression:left ( '<-' | '+=' | '-=' | '*=' | '/=' | '%=' ):operator ( expression | table ):right ) 172 | 173 | table ::= >0( '{' table_slots? '}' ( '.' expression )? ) 174 | 175 | table_slots ::= table_slot ( ','? table_slot )* ','? 176 | 177 | table_slot ::= identifier '=' ( expression | table ) 178 | | '[' expression ']' '=' ( expression | table ) 179 | | expression ':' ( expression | table ) 180 | | function_declaration 181 | 182 | delete_expression ::= 'delete' expression ( ';' | '\n' ) 183 | 184 | var_statement ::= 'var' identifier '=' expression 185 | 186 | deref_expression ::= 15( expression '.' identifier ) 187 | 188 | index_expression ::= <15( expression:object '[' expression:index ']' ) 189 | 190 | call_expression ::= <14( ( expression:function | 'rawcall' ) '(' call_args? ')' ) 191 | 192 | call_args ::= ( expression | table ) ( ',' ( expression | table ) )* 193 | 194 | anonymous_function ::= 'function' '(' parameters? ')' _statement 195 | 196 | lambda_expression ::= '@' '(' parameters? ')' expression 197 | 198 | parenthesized_expression ::= -1( '(' expression ')' ) 199 | 200 | clone_expression ::= >0( 'clone' expression ) 201 | 202 | array ::= >0( '[' ( expression ( ',' expression )* )? ','? ']' ) 203 | 204 | identifier ::= /[a-zA-Z_][a-zA-Z0-9_]*/ 205 | 206 | global_variable ::= '::' identifier 207 | 208 | integer ::= @( /0/ | /-?[1-9][0-9]*/ | /0[xX][0-9A-Fa-f]+/ | /'''[.]+'''/ | /0[0-7]+/ ) 209 | 210 | float ::= @( /-?[0-9]+\.[0-9]+/ | /[0-9]+\.[eE][+-]?[0-9]+/ ) 211 | 212 | string ::= '"' ( string_content | _escape_sequence )* '"' 213 | 214 | string_content ::= !( 1( /[^"\\]+/ ) ) 215 | 216 | char ::= "'" ( escape_sequence | /[^\\']/ ) "'" 217 | | "'#'" 218 | 219 | _escape_sequence ::= 2( !( '\\' /[^abfnrtvxu'\"\\\?]/ ) ) 220 | | 1( escape_sequence ) 221 | 222 | escape_sequence ::= !( '\\' ( /[^xu0-7]/ | /[0-7]{1,3}/ | /x[0-9a-fA-F]{2}/ | /u[0-9a-fA-F]{4}/ | /u\{[0-9a-fA-F]+\}/ ) ) 223 | 224 | bool ::= 'true' 225 | | 'false' 226 | 227 | null ::= 'null' 228 | 229 | comment ::= @( '#' /.*/ | '//' /(\\(.|\r?\n)|[^\\\n])*/ | '/*' /[^*]*\*+([^/*][^*]*\*+)*/ '/' ) 230 | 231 | -------------------------------------------------------------------------------- /examples/swift.ebnf: -------------------------------------------------------------------------------- 1 | ; repository: https://github.com/tree-sitter/tree-sitter-swift.git 2 | ; commit: db675450dcc1478ee128c96ecc61c13272431aab 3 | ; json from: tree-sitter-swift/src/grammar.json 4 | ; From /tmp/tslua/swift0.json 5 | ; EBNF to generate grammar.js at 6 | ; https://mingodad.github.io/lua-wasm-playground/ 7 | ; based on https://github.com/eatkins/tree-sitter-ebnf-generator 8 | ; see also https://mingodad.github.io/plgh/json2ebnf.html 9 | 10 | 11 | extras ::= { 12 | /\s+/ 13 | comment 14 | } 15 | 16 | conflicts ::= { 17 | { _variable_declaration_head value_binding_pattern } 18 | { _condition _condition_clause } 19 | { _variable_name _expression } 20 | { _array_declaration _dictionary_declaration } 21 | } 22 | 23 | word ::= identifier 24 | 25 | rules: 26 | 27 | program ::= _statement* 28 | 29 | _statement ::= ( _expression | _declaration | _loop_statement | if_statement | guard_statement | switch_statement | labeled_statement | break_statement | continue_statement | fallthrough_statement | return_statement | throw_statement | defer_statement | do_statement | build_configuration_statement | diagnostic_statement | line_control_statement ) ( ';' | /\n/ ) 30 | 31 | _loop_statement ::= for_statement 32 | | while_statement 33 | | repeat_while_statement 34 | 35 | for_statement ::= 'for' 'case'? _pattern _type_annotation? 'in' _expression _code_block 36 | 37 | while_statement ::= 'while' _condition_clause _code_block 38 | 39 | _condition_clause ::= _expression ( ',' _condition ( ',' _condition )* )? 40 | | _condition ( ',' _condition )* 41 | | availability_condition ',' _expression 42 | 43 | _condition ::= availability_condition 44 | | case_condition 45 | | optional_binding_condition 46 | 47 | _availability_platforms ::= 'iOS' 48 | | 'iOSApplicationExtension' 49 | | 'macOS' 50 | | 'macOSApplicationExtension' 51 | | 'watchOS' 52 | | 'tvOS' 53 | 54 | availability_condition ::= '#available' '(' ( '*' | _availability_platforms @( /[0-9]+/ ( '.' /[0-9]+/ ( '.' /[0-9]+/ )? )? ) ) ( ',' ( '*' | _availability_platforms @( /[0-9]+/ ( '.' /[0-9]+/ ( '.' /[0-9]+/ )? )? ) ) )* ')' 55 | 56 | case_condition ::= 'case' _pattern '=' _expression 57 | 58 | optional_binding_condition ::= >40( ( 'let' | 'var' ) optional_binding ( ',' optional_binding ( ',' optional_binding )* )? ) 59 | 60 | optional_binding ::= _pattern '=' _expression 61 | 62 | repeat_while_statement ::= 'repeat' _code_block 'while' _expression 63 | 64 | if_statement ::= 'if' _condition_clause _code_block ( 'else' ( _code_block | if_statement ) )? 65 | 66 | guard_statement ::= 'guard' _condition_clause 'else' _code_block 67 | 68 | switch_statement ::= 'switch' _expression '{' case_statement* '}' 69 | 70 | case_statement ::= ( 'case' _pattern ( ',' _pattern )* ':' | 'default' ':' ) _statement* 71 | 72 | _code_block ::= '{' _statement* '}' 73 | 74 | labeled_statement ::= identifier ':' ( _loop_statement | if_statement ) 75 | 76 | break_statement ::= 'break' identifier? 77 | 78 | continue_statement ::= 'continue' identifier? 79 | 80 | fallthrough_statement ::= 'fallthrough' 81 | 82 | return_statement ::= 'return' _expression? 83 | 84 | throw_statement ::= 'throw' _expression? 85 | 86 | defer_statement ::= 'defer' _code_block 87 | 88 | do_statement ::= 'do' _code_block catch_clause* 89 | 90 | catch_clause ::= 'catch' _pattern? _code_block 91 | 92 | build_configuration_statement ::= '#if' _build_configuration _statement* ( '#elseif' _build_configuration _statement* )* ( '#else' _statement* )? '#endif' 93 | 94 | _build_configuration ::= 'os' '(' ( 'iOS' | 'macOS' | 'watchOS' | 'tvOS' | 'Linux' ) ')' 95 | | 'arch' '(' ( 'i386' | 'x86_64' | 'arm' | 'arm64' ) ')' 96 | | 'canImport' '(' identifier ')' 97 | | 'targetEnvironment' '(' ( 'simulator' | 'macCatalyst' ) ')' 98 | | ( 'compiler' | 'swift' ) '(' ( '>=' | '<' ) semantic_version ')' 99 | | identifier 100 | | boolean_literal 101 | | '(' _build_configuration ')' 102 | | '!' _build_configuration 103 | | <60( _build_configuration '&&' _build_configuration ) 104 | | <50( _build_configuration '||' _build_configuration ) 105 | 106 | line_control_statement ::= '#line' ( /[0-9]+/ static_string_literal )? 107 | 108 | diagnostic_statement ::= ( '#error' | '#warning' ) '(' static_string_literal ')' 109 | 110 | _declaration ::= import_declaration 111 | | constant_declaration 112 | | variable_declaration 113 | | typealias_declaration 114 | | function_declaration 115 | | enum_declaration 116 | | struct_declaration 117 | | class_declaration 118 | | protocol_declaration 119 | | initializer_declaration 120 | | deinitializer_declaration 121 | | extension_declaration 122 | | subscript_declaration 123 | | operator_declaration 124 | 125 | import_declaration ::= 'import' ( 'typealias' | 'struct' | 'class' | 'enum' | 'protocol' | 'var' | 'func' )? ( identifier | operator ) ( '.' ( identifier | operator ) )* 126 | 127 | constant_declaration ::= modifier* 'let' _pattern_initializer ( ',' _pattern_initializer )* 128 | 129 | _pattern_initializer ::= _pattern:name ( _type_annotation:type )? ( '=' _expression:value )? 130 | 131 | variable_declaration ::= _variable_declaration_head ( _pattern_initializer ( ',' _pattern_initializer )* | _variable_name:name _type_annotation:type ( _code_block | _getter_setter_keyword_block ) ) 132 | 133 | _variable_declaration_head ::= modifier* 'var' 134 | 135 | _variable_name ::= identifier 136 | 137 | _getter_setter_keyword_block ::= '{' ( _getter_keyword_clause _setter_keyword_clause? | _setter_keyword_clause _getter_keyword_clause ) '}' 138 | 139 | _getter_keyword_clause ::= 'get' 140 | 141 | _setter_keyword_clause ::= 'set' 142 | 143 | typealias_declaration ::= _typealias_head '=' type 144 | 145 | _typealias_head ::= modifier? 'typealias' identifier 146 | 147 | function_declaration ::= _function_head _function_signature _code_block? 148 | 149 | _function_head ::= modifier* 'func' ( identifier | operator ):name 150 | 151 | _function_signature ::= generic_clause? parameter_list ( 'throws' | 'rethrows' )? _function_return_statement? 152 | 153 | parameter_list ::= '(' ( _single_parameter -> parameter_declaration ( ',' _single_parameter -> parameter_declaration )* )? ')' 154 | 155 | _function_return_statement ::= '->' ( type ( '!' | '?' )? ):return 156 | 157 | _parameter_clause ::= '(' ( _single_parameter ( ',' _single_parameter )* ','? )? ')' 158 | 159 | _single_parameter ::= ( identifier | '_' )? identifier? _type_annotation ( '!' | '?' )? ( '=' _expression )? 160 | 161 | enum_declaration ::= modifier* 'indirect'? 'enum' identifier '{' ( _declaration | case_declaration )* '}' 162 | 163 | case_declaration ::= 'indirect'? 'case' identifier ( tuple_type | '=' ( static_string_literal | boolean_literal ) )? 164 | 165 | modifier ::= _access_control_modifier 166 | | _declaration_modifier 167 | 168 | _declaration_modifier ::= 'static' 169 | | 'final' 170 | | 'class' 171 | 172 | _access_control_modifier ::= 'public' 173 | | 'private' 174 | | 'fileprivate' 175 | | 'open' 176 | | 'internal' 177 | | 'private(set)' 178 | | 'fileprivate(set)' 179 | | 'internal(set)' 180 | 181 | generic_clause ::= '<' ( _single_generic_parameter ( ',' _single_generic_parameter )* )? '>' 182 | 183 | _single_generic_parameter ::= identifier:name ( ':' _type_declarator:type )? 184 | 185 | struct_declaration ::= modifier* 'struct' identifier '{' _declaration* '}' 186 | 187 | class_declaration ::= modifier* 'class' identifier '{' _declaration* '}' 188 | 189 | protocol_declaration ::= modifier* 'protocol' identifier '{' ( protocol_variable_declaration | protocol_method_declaration | protocol_initializer_declaration | protocol_subscript_declaration | protocol_typealias_declaration | associatedtype_declaration )* '}' 190 | 191 | protocol_variable_declaration ::= _variable_declaration_head identifier _type_annotation _getter_setter_keyword_block 192 | 193 | protocol_method_declaration ::= _function_head _function_signature 194 | 195 | protocol_initializer_declaration ::= _initializer_head _parameter_clause ( 'throws' | 'rethrows' )? 196 | 197 | protocol_subscript_declaration ::= _subscript_head _subscript_result _getter_setter_keyword_block 198 | 199 | protocol_typealias_declaration ::= _typealias_head ( '=' type )? 200 | 201 | associatedtype_declaration ::= 'associatedtype' identifier _type_annotation? 202 | 203 | initializer_declaration ::= _initializer_head _parameter_clause ( 'throws' | 'rethrows' )? _code_block 204 | 205 | _initializer_head ::= 'init' ( '!' | '?' )? 206 | 207 | deinitializer_declaration ::= 'deinit' _code_block 208 | 209 | extension_declaration ::= modifier* 'extension' _type_identifier '{' _declaration* '}' 210 | 211 | subscript_declaration ::= _subscript_head _subscript_result ( _code_block | _getter_setter_keyword_block ) 212 | 213 | _subscript_head ::= 'subscript' _parameter_clause 214 | 215 | _subscript_result ::= '->' type 216 | 217 | operator_declaration ::= 'prefix' 'operator' operator '{' '}' 218 | | 'postfix' 'operator' operator '{' '}' 219 | | 'infix' 'operator' operator '{' ( precedence_clause? associativity_clause? | associativity_clause precedence_clause? ) '}' 220 | 221 | precedence_clause ::= 'precedence' /[0-9]|[1-9][0-9]|1[0-9][0-9]|2([0-4][0-9]|5[0-5])/ 222 | 223 | associativity_clause ::= 'associativity' ( 'left' | 'right' | 'none' ) 224 | 225 | _pattern ::= wildcard_pattern 226 | | value_binding_pattern 227 | | enum_case_pattern 228 | | optional_pattern 229 | | is_pattern 230 | | as_pattern 231 | | _expression 232 | 233 | wildcard_pattern ::= '_' 234 | 235 | value_binding_pattern ::= ( 'var' | 'let' ) _pattern 236 | 237 | enum_case_pattern ::= _type_identifier? '.' identifier ( _tuple_declaration -> tuple )? 238 | 239 | optional_pattern ::= 20( _pattern '?' ) 240 | 241 | is_pattern ::= 'is' type 242 | 243 | as_pattern ::= 10( _pattern 'as' type ) 244 | 245 | _expression ::= identifier 246 | | number 247 | | boolean_literal -> boolean 248 | | nil 249 | | static_string_literal -> string 250 | | _array_declaration -> array 251 | | _dictionary_declaration -> dictionary 252 | | _tuple_declaration -> tuple 253 | 254 | boolean_literal ::= 'true' 255 | | 'false' 256 | 257 | static_string_literal ::= /"((\\([\\0tnr'"]|u\{[a-fA-F0-9]{1,8}\}))|[^"\\\u000a\u000d])*"/ 258 | 259 | number ::= @( ( '0x' | '0X' ) /[\da-fA-F](_?[\da-fA-F])*/ | /[-\+]/? ( '0' | '0'? /[1-9]/ ( '_'? /\d(_?\d)*/ )? ) '.' /\d(_?\d)*/? ( ( 'e' | 'E' ) /[-\+]/? /\d(_?\d)*/ )? | /[-\+]/? '.' /\d(_?\d)*/ ( ( 'e' | 'E' ) /[-\+]/? /\d(_?\d)*/ )? | /[-\+]/? ( '0' | '0'? /[1-9]/ ( '_'? /\d(_?\d)*/ )? ) ( 'e' | 'E' ) /[-\+]/? /\d(_?\d)*/ | /[-\+]/? /\d(_?\d)*/ | ( '0b' | '0B' ) /[0-1](_?[0-1])*/ | ( '0o' | '0O' ) /[0-7](_?[0-7])*/ | ( ( '0x' | '0X' ) /[\da-fA-F](_?[\da-fA-F])*/ | ( '0b' | '0B' ) /[0-1](_?[0-1])*/ | ( '0o' | '0O' ) /[0-7](_?[0-7])*/ | /\d(_?\d)*/ ) 'n' ) 260 | 261 | nil ::= 'nil' 262 | 263 | type ::= tuple_type -> tuple 264 | | standard_type 265 | | _type_identifier 266 | 267 | _type_declarator ::= standard_type 268 | | tuple_type 269 | | array_type 270 | | dictionary_type 271 | | identifier -> type_identifier 272 | 273 | standard_type ::= @( 'Bool' | 'Character' | 'StaticString' | 'String' | 'Void' | 'Double' | 'Float' | 'Int' | 'UInt' | 'UInt8' | 'UInt16' | 'UInt32' | 'UInt64' | 'Int8' | 'Int16' | 'Int32' | 'Int64' | 'Float32' | 'Float64' | 'Float80' ) 274 | 275 | tuple_type ::= '(' ( ( _variable_name _type_annotation | _type_declarator ) ( ',' ( _variable_name _type_annotation | _type_declarator ) )* )? ')' 276 | 277 | _tuple_declaration ::= '(' ( ( identifier ':' )? _expression ( ',' ( identifier ':' )? _expression )* )? ')' 278 | 279 | array_type ::= _array_type_shorthand 280 | | _array_type_full 281 | 282 | _array_type_full ::= 'Array' '<' _type_declarator '>' 283 | 284 | _array_type_shorthand ::= '[' _type_declarator ']' 285 | 286 | _array_declaration ::= '[' ( _expression? ( ',' _expression? )* )? ']' 287 | 288 | dictionary_type ::= _dictionary_type_shorthand 289 | | _dictionary_type_full 290 | 291 | _dictionary_type_full ::= 'Dictionary' '<' _type_declarator ',' _type_declarator '>' 292 | 293 | _dictionary_type_shorthand ::= '[' _type_declarator ':' _type_declarator ']' 294 | 295 | _dictionary_declaration ::= '[' ( _expression? ':' _expression? ( ',' _expression? ':' _expression? )* )? ']' 296 | 297 | _type_annotation ::= ':' ( type | array_type | dictionary_type ) 298 | 299 | _type_identifier ::= <30( _type_name ( '.' _type_identifier )? ) 300 | 301 | _type_name ::= identifier 302 | 303 | identifier ::= @( /[A-Za-z_]/ ( /[A-Za-z_]/ | /[0-9]/ )*? | '`' /[A-Za-z_]/ ( /[A-Za-z_]/ | /[0-9]/ )*? '`' ) 304 | 305 | operator ::= @( ( '/' | '=' | '-' | '+' | '!' | '*' | '%' | '<' | '>' | '&' | '|' | '^' | '~' | '?' )+ ) 306 | 307 | semantic_version ::= /(\d+\.)?(\d+\.)?(\*|\d+)/ 308 | 309 | comment ::= @( /\/{2,3}[^\/].*/ | /\/\*{1,}[^*]*\*+([^\/*][^*]*\*+)*\// ) 310 | 311 | -------------------------------------------------------------------------------- /examples/teal.ebnf: -------------------------------------------------------------------------------- 1 | ; repository: https://github.com/euclidianAce/tree-sitter-teal.git 2 | ; commit: 19b02da829d1721a521bf7b802eb80a50bd53aab 3 | ; json from: tree-sitter-teal/src/grammar.json 4 | ; From /tmp/tslua/teal0.json 5 | ; EBNF to generate grammar.js at 6 | ; https://mingodad.github.io/lua-wasm-playground/ 7 | ; based on https://github.com/eatkins/tree-sitter-ebnf-generator 8 | ; see also https://mingodad.github.io/plgh/json2ebnf.html 9 | 10 | 11 | externals ::= { 12 | comment 13 | _long_string_start 14 | _long_string_char 15 | _long_string_end 16 | _short_string_start 17 | _short_string_char 18 | _short_string_end 19 | } 20 | 21 | extras ::= { 22 | comment 23 | /[\s\n]/ 24 | } 25 | 26 | inline ::= { 27 | scope 28 | _partypelist 29 | _parnamelist 30 | _type_list_maybe_vararg 31 | } 32 | 33 | conflicts ::= { 34 | { _var table_entry } 35 | { return_type } 36 | } 37 | 38 | word ::= identifier 39 | 40 | rules: 41 | 42 | program ::= !( /#![^\n\r]*/ )? -> shebang_comment _statement* 43 | 44 | _statement ::= 1( ( var_declaration | var_assignment | type_declaration | record_declaration | enum_declaration | return_statement | break | _for_statement | do_statement | while_statement | repeat_statement | function_call | function_statement | if_statement | '::' identifier -> label '::' | goto ) ';'? ) 45 | 46 | return_statement ::= >1( 'return' ( _expression ( ',' _expression )* | '(' _expression ( ',' _expression )* ')' )? ) 47 | 48 | break ::= 'break' 49 | 50 | if_statement ::= 'if' _expression:condition 'then' _statement* elseif_block* else_block? 'end' 51 | 52 | elseif_block ::= 'elseif' _expression:condition 'then' _statement* 53 | 54 | else_block ::= 'else' _statement* 55 | 56 | numeric_for_statement ::= 'for' identifier:variable '=' _expression:initializer ',' _expression:target ( ',' _expression:step )? ( do_statement -> for_body ):body 57 | 58 | generic_for_statement ::= 'for' ( identifier ( ',' identifier )* ):variable 'in' ( _expression ( ',' _expression )* ):iterator ( do_statement -> for_body ):body 59 | 60 | _for_statement ::= numeric_for_statement 61 | | generic_for_statement 62 | 63 | while_statement ::= 'while' _expression:condition do_statement -> while_body 64 | 65 | repeat_statement ::= 'repeat' _statement* 'until' _expression:condition 66 | 67 | do_statement ::= 'do' _statement* 'end' 68 | 69 | _expression ::= identifier 70 | | _var 71 | | number 72 | | string 73 | | boolean 74 | | nil 75 | | table_constructor 76 | | anon_function 77 | | function_call 78 | | _prefix_expression 79 | | bin_op 80 | | unary_op 81 | | varargs 82 | | type_cast 83 | | parenthesized_expression 84 | 85 | parenthesized_expression ::= '(' _expression ')' 86 | 87 | unary_op ::= <12( ( ( 'not' | '#' | '-' | '~' ) -> op ):op _expression:right ) 88 | 89 | bin_op ::= <1( _expression:left ( 'or' -> op ):op _expression:right ) 90 | | <2( _expression:left ( 'and' -> op ):op _expression:right ) 91 | | <4( _expression:left ( '<' -> op ):op _expression:right ) 92 | | <4( _expression:left ( '<=' -> op ):op _expression:right ) 93 | | <4( _expression:left ( '==' -> op ):op _expression:right ) 94 | | <4( _expression:left ( '~=' -> op ):op _expression:right ) 95 | | <4( _expression:left ( '>=' -> op ):op _expression:right ) 96 | | <4( _expression:left ( '>' -> op ):op _expression:right ) 97 | | <5( _expression:left ( '|' -> op ):op _expression:right ) 98 | | <6( _expression:left ( '~' -> op ):op _expression:right ) 99 | | <7( _expression:left ( '&' -> op ):op _expression:right ) 100 | | <8( _expression:left ( '<<' -> op ):op _expression:right ) 101 | | <8( _expression:left ( '>>' -> op ):op _expression:right ) 102 | | <10( _expression:left ( '+' -> op ):op _expression:right ) 103 | | <10( _expression:left ( '-' -> op ):op _expression:right ) 104 | | <11( _expression:left ( '*' -> op ):op _expression:right ) 105 | | <11( _expression:left ( '/' -> op ):op _expression:right ) 106 | | <11( _expression:left ( '//' -> op ):op _expression:right ) 107 | | <11( _expression:left ( '%' -> op ):op _expression:right ) 108 | | >9( _expression:left ( '..' -> op ):op _expression:right ) 109 | | >13( _expression:left ( '^' -> op ):op _expression:right ) 110 | | >3( _expression:left ( 'is' -> op ):op _type:right ) 111 | 112 | type_cast ::= >100( _expression 'as' ( _type | type_tuple ) ) 113 | 114 | type_tuple ::= 10( '(' _type ( ',' _type )* ')' ) 115 | 116 | type_union ::= <100( _type '|' _type ) 117 | 118 | var_declarator ::= identifier:name ( '<' ( identifier -> attribute ):attribute '>' )? 119 | 120 | var_declarators ::= var_declarator -> var ( ',' var_declarator -> var )* 121 | 122 | expressions ::= _expression ( ',' _expression )* 123 | 124 | var_declaration ::= scope var_declarators:declarators ( type_annotation:type_annotation )? ( '=' expressions:initializers )? 125 | 126 | _type_def ::= 'type' identifier:name '=' ( _type | _newtype ):value 127 | 128 | type_declaration ::= scope:scope _type_def 129 | | record_declaration 130 | | enum_declaration 131 | 132 | assignment_variables ::= _var -> var ( ',' _var -> var )* 133 | 134 | var_assignment ::= assignment_variables:variables '=' expressions:expressions 135 | 136 | _prefix_expression ::= 10( _var | function_call | parenthesized_expression ) 137 | 138 | method_index ::= _prefix_expression ':' identifier:key 139 | 140 | arguments ::= '(' ( _expression ( ',' _expression )* )? ')' 141 | | string 142 | | table_constructor 143 | 144 | function_call ::= 10( ( _prefix_expression | method_index ):called_object arguments:arguments ) 145 | 146 | table_entry ::= '[' _expression:expr_key ']' '=' _expression:value 147 | | 1( identifier:key ( ':' _type )?:type '=' _expression:value ) 148 | | 1( _expression:value ) 149 | 150 | table_constructor ::= '{' ( table_entry ( ( ',' | ';' ) table_entry )* )? ( ',' | ';' )? '}' 151 | 152 | function_name ::= identifier:base ( ( '.' identifier:entry )* ':' identifier:method | ( '.' identifier:entry )+ ) 153 | 154 | scope ::= ( 'local' | 'global' ):scope 155 | 156 | function_statement ::= scope 'function' identifier:name function_signature:signature function_body:body 157 | | 'function' function_name:name function_signature:signature function_body:body 158 | 159 | variadic_type ::= 999( _type '...' ) 160 | 161 | _type_list_maybe_vararg ::= _type ( ',' _type )* ( ',' variadic_type )? 162 | 163 | return_type ::= variadic_type 164 | | ~1( _type_list_maybe_vararg ) 165 | | ~10( '(' _type_list_maybe_vararg ')' ) 166 | 167 | _partypelist ::= _partype -> arg ( ',' _partype -> arg )* 168 | 169 | _partype ::= ( identifier:name ':' )? _type:type 170 | 171 | _parnamelist ::= _parname -> arg ( ',' _parname -> arg )* 172 | 173 | _parname ::= identifier:name ( ':' _type:type )? 174 | 175 | typeargs ::= '<' identifier ( ',' identifier )* '>' 176 | 177 | anon_function ::= 'function' function_signature:signature function_body:body 178 | 179 | _annotated_var_arg ::= '...' ':' _type:type 180 | 181 | signature_arguments ::= '(' ( _parnamelist | _parnamelist ',' _annotated_var_arg -> varargs | _annotated_var_arg -> varargs )? ')' 182 | 183 | function_signature ::= typeargs?:typeargs ( signature_arguments -> arguments ):arguments ( ':' return_type:return_type )? 184 | 185 | function_body ::= _statement* 'end' 186 | 187 | record_field ::= identifier:key ':' _type:type 188 | | '[' string:key ']' ':' _type:type 189 | | ( 'type' -> identifier ):key ':' _type:type 190 | | ( 'record' -> identifier ):key ':' _type:type 191 | | ( 'enum' -> identifier ):key ':' _type:type 192 | | ( 'userdata' -> identifier ):key ':' _type:type 193 | | ( 'metamethod' -> identifier ):key ':' _type:type 194 | 195 | _record_entry ::= record_field -> field 196 | | _type_def -> typedef 197 | | _record_def -> record_declaration 198 | | _enum_def -> enum_declaration 199 | 200 | metamethod_annotation ::= 'metamethod' identifier:name ':' _type:type 201 | 202 | record_body ::= ( '{' _type -> record_array_type '}' )? ( _record_entry | 'userdata' -> userdata | ( metamethod_annotation -> metamethod ):metamethod )* 'end' 203 | 204 | _record_def ::= 'record' identifier:name typeargs?:typeargs record_body:record_body 205 | 206 | record_declaration ::= scope _record_def 207 | 208 | enum_body ::= string* 'end' 209 | 210 | _enum_def ::= 'enum' identifier:name enum_body:enum_body 211 | 212 | enum_declaration ::= scope _enum_def 213 | 214 | anon_record ::= 'record' typeargs? record_body:record_body 215 | 216 | _anon_enum ::= 'enum' enum_body 217 | 218 | _newtype ::= _anon_enum 219 | | anon_record 220 | 221 | type_annotation ::= ':' _type ( ',' _type )* 222 | 223 | _type ::= 2( simple_type | type_index | table_type | function_type | type_union | '(' _type ')' ) 224 | 225 | typearg_params ::= >1000( '<' _type ( ',' _type )* '>' ) 226 | 227 | type_index ::= >1000( ( identifier | type_index ) '.' identifier ( typearg_params -> typeargs )? ) 228 | 229 | simple_type ::= >1000( identifier:name ( typearg_params -> typeargs )? ) 230 | 231 | table_type ::= '{' ( _type:value_type | _type:key_type ':' _type:value_type | _type:tuple_type ( ',' _type:tuple_type )+ ) '}' 232 | 233 | function_type_args ::= '(' ( _partypelist ( ',' _annotated_var_arg -> varargs )? | _annotated_var_arg -> varargs )? ')' 234 | 235 | function_type ::= >1( 'function' typeargs?:typeargs ( ( function_type_args -> arguments ):arguments ( ':' return_type:return_type )? )? ) 236 | 237 | goto ::= 'goto' identifier 238 | 239 | index ::= _prefix_expression ( ( '.' identifier ):key | ( '[' _expression ']' ):expr_key ) 240 | 241 | _var ::= 1( identifier | index ) 242 | 243 | varargs ::= '...' 244 | 245 | identifier ::= /[a-zA-Z_][a-zA-Z_0-9]*/ 246 | 247 | number ::= /\d+(\.\d+)?(e\d+)?/i 248 | | /\.\d+(e\d+)?/i 249 | | /0x[0-9a-fA-F]+(\.[0-9a-fA-F]+)?(p\d+)?/ 250 | 251 | boolean ::= 'true' 252 | | 'false' 253 | 254 | _short_string_content ::= ( format_specifier | escape_sequence | !( 1( '%' ) ) | 0( _short_string_char ) )+ -> string_content 255 | 256 | _long_string_content ::= ( format_specifier | _long_string_char | !( 1( '%' ) ) )+ -> string_content 257 | 258 | string ::= 2( ( _short_string_start -> "short_string_start" ):start _short_string_content?:content ( _short_string_end -> "short_string_end" ):end | ( _long_string_start -> "long_string_start" ):start _long_string_content?:content ( _long_string_end -> "long_string_end" ):end ) 259 | 260 | format_specifier ::= !( 3( '%' ( '%' | ( '+' | '-' )? ' '? '#'? /[0-9]+/? '.'? /[0-9]+/? /[AaEefGgcdiouXxpqs]/ ) ) ) 261 | 262 | escape_sequence ::= !( 3( '\\' ( /[abfnrtvz"'\\]/ | 'x' /[0-9a-fA-F]{2}/ | 'd' /[0-7]{3}/ | 'u{' /[0-9a-fA-F]{1,8}/ '}' ) ) ) 263 | 264 | nil ::= 'nil' 265 | 266 | -------------------------------------------------------------------------------- /examples/tree-sitter-json-schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "title": "tree-sitter grammar specification", 4 | "type": "object", 5 | 6 | "required": ["name", "rules"], 7 | 8 | "additionalProperties": false, 9 | 10 | "properties": { 11 | "name": { 12 | "description": "the name of the grammar", 13 | "type": "string", 14 | "pattern": "^[a-zA-Z_]\\w*" 15 | }, 16 | 17 | "inherits": { 18 | "description": "the name of the parent grammar", 19 | "type": "string", 20 | "pattern": "^[a-zA-Z_]\\w*" 21 | }, 22 | 23 | "rules": { 24 | "type": "object", 25 | "patternProperties": { 26 | "^[a-zA-Z_]\\w*$": { 27 | "$ref": "#/definitions/rule" 28 | } 29 | }, 30 | "additionalProperties": false 31 | }, 32 | 33 | "extras": { 34 | "type": "array", 35 | "uniqueItems": true, 36 | "items": { 37 | "$ref": "#/definitions/rule" 38 | } 39 | }, 40 | 41 | "precedences": { 42 | "type": "array", 43 | "uniqueItems": true, 44 | "items": { 45 | "type": "array", 46 | "uniqueItems": true, 47 | "items": { 48 | "oneOf": [ 49 | { "$ref": "#/definitions/string-rule" }, 50 | { "$ref": "#/definitions/symbol-rule" } 51 | ] 52 | } 53 | } 54 | }, 55 | 56 | "externals": { 57 | "type": "array", 58 | "uniqueItems": true, 59 | "items": { 60 | "$ref": "#/definitions/rule" 61 | } 62 | }, 63 | 64 | "inline": { 65 | "type": "array", 66 | "uniqueItems": true, 67 | "items": { 68 | "type": "string", 69 | "pattern": "^[a-zA-Z_]\\w*$" 70 | } 71 | }, 72 | 73 | "conflicts": { 74 | "type": "array", 75 | "uniqueItems": true, 76 | "items": { 77 | "type": "array", 78 | "uniqueItems": true, 79 | "items": { 80 | "type": "string", 81 | "pattern": "^[a-zA-Z_]\\w*$" 82 | } 83 | } 84 | }, 85 | 86 | "word": { 87 | "type": "string", 88 | "pattern": "^[a-zA-Z_]\\w*" 89 | }, 90 | 91 | "supertypes": { 92 | "description": "A list of hidden rule names that should be considered supertypes in the generated node types file. See https://tree-sitter.github.io/tree-sitter/using-parsers#static-node-types.", 93 | "type": "array", 94 | "uniqueItems": true, 95 | "items": { 96 | "description": "the name of a rule in `rules` or `extras`", 97 | "type": "string" 98 | } 99 | } 100 | }, 101 | 102 | "definitions": { 103 | "blank-rule": { 104 | "type": "object", 105 | "properties": { 106 | "type": { 107 | "type": "string", 108 | "pattern": "^BLANK$" 109 | } 110 | }, 111 | "required": ["type"] 112 | }, 113 | 114 | "string-rule": { 115 | "type": "object", 116 | "properties": { 117 | "type": { 118 | "type": "string", 119 | "pattern": "^STRING$" 120 | }, 121 | "value": { 122 | "type": "string", 123 | "minLength": 1 124 | } 125 | }, 126 | "required": ["type", "value"] 127 | }, 128 | 129 | "pattern-rule": { 130 | "type": "object", 131 | "properties": { 132 | "type": { 133 | "type": "string", 134 | "pattern": "^PATTERN$" 135 | }, 136 | "value": { "type": "string", "minLength": 1 }, 137 | "flags": { "type": "string" } 138 | }, 139 | "required": ["type", "value"] 140 | }, 141 | 142 | "symbol-rule": { 143 | "type": "object", 144 | "properties": { 145 | "type": { 146 | "type": "string", 147 | "pattern": "^SYMBOL$" 148 | }, 149 | "name": { "type": "string" } 150 | }, 151 | "required": ["type", "name"] 152 | }, 153 | 154 | "seq-rule": { 155 | "type": "object", 156 | "properties": { 157 | "type": { 158 | "type": "string", 159 | "pattern": "^SEQ$" 160 | }, 161 | "members": { 162 | "type": "array", 163 | "items": { 164 | "$ref": "#/definitions/rule" 165 | } 166 | } 167 | }, 168 | "required": ["type", "members"] 169 | }, 170 | 171 | "choice-rule": { 172 | "type": "object", 173 | "properties": { 174 | "type": { 175 | "type": "string", 176 | "pattern": "^CHOICE$" 177 | }, 178 | "members": { 179 | "type": "array", 180 | "minItems": 2, 181 | "items": { 182 | "$ref": "#/definitions/rule" 183 | } 184 | } 185 | }, 186 | "required": ["type", "members"] 187 | }, 188 | 189 | "alias-rule": { 190 | "type": "object", 191 | "properties": { 192 | "type": { 193 | "type": "string", 194 | "pattern": "^ALIAS$" 195 | }, 196 | "value": { 197 | "type": "string" 198 | }, 199 | "named": { 200 | "type": "boolean" 201 | }, 202 | "content": { 203 | "$ref": "#/definitions/rule" 204 | } 205 | }, 206 | "required": ["type", "named", "content", "value"] 207 | }, 208 | 209 | "repeat-rule": { 210 | "type": "object", 211 | "properties": { 212 | "type": { 213 | "type": "string", 214 | "pattern": "^REPEAT$" 215 | }, 216 | "content": { 217 | "$ref": "#/definitions/rule" 218 | } 219 | }, 220 | "required": ["type", "content"] 221 | }, 222 | 223 | "repeat1-rule": { 224 | "type": "object", 225 | "properties": { 226 | "type": { 227 | "type": "string", 228 | "pattern": "^REPEAT1$" 229 | }, 230 | "content": { 231 | "$ref": "#/definitions/rule" 232 | } 233 | }, 234 | "required": ["type", "content"] 235 | }, 236 | 237 | "token-rule": { 238 | "type": "object", 239 | "properties": { 240 | "type": { 241 | "type": "string", 242 | "pattern": "^(TOKEN|IMMEDIATE_TOKEN)$" 243 | }, 244 | "content": { 245 | "$ref": "#/definitions/rule" 246 | } 247 | }, 248 | "required": ["type", "content"] 249 | }, 250 | 251 | "field-rule": { 252 | "properties": { 253 | "name": { "type": "string" }, 254 | "type": { 255 | "type": "string", 256 | "pattern": "^FIELD$" 257 | }, 258 | "content": { 259 | "$ref": "#/definitions/rule" 260 | } 261 | }, 262 | "required": ["name", "type", "content"] 263 | }, 264 | 265 | "prec-rule": { 266 | "type": "object", 267 | "properties": { 268 | "type": { 269 | "type": "string", 270 | "pattern": "^(PREC|PREC_LEFT|PREC_RIGHT|PREC_DYNAMIC)$" 271 | }, 272 | "value": { 273 | "oneOf": [ 274 | { "type": "integer" }, 275 | { "type": "string" } 276 | ] 277 | }, 278 | "content": { 279 | "$ref": "#/definitions/rule" 280 | } 281 | }, 282 | "required": ["type", "content", "value"] 283 | }, 284 | 285 | "rule": { 286 | "oneOf": [ 287 | { "$ref": "#/definitions/alias-rule" }, 288 | { "$ref": "#/definitions/blank-rule" }, 289 | { "$ref": "#/definitions/string-rule" }, 290 | { "$ref": "#/definitions/pattern-rule" }, 291 | { "$ref": "#/definitions/symbol-rule" }, 292 | { "$ref": "#/definitions/seq-rule" }, 293 | { "$ref": "#/definitions/choice-rule" }, 294 | { "$ref": "#/definitions/repeat1-rule" }, 295 | { "$ref": "#/definitions/repeat-rule" }, 296 | { "$ref": "#/definitions/token-rule" }, 297 | { "$ref": "#/definitions/field-rule" }, 298 | { "$ref": "#/definitions/prec-rule" } 299 | ] 300 | } 301 | } 302 | } 303 | -------------------------------------------------------------------------------- /examples/vimdoc.ebnf: -------------------------------------------------------------------------------- 1 | ; repository: https://github.com/neovim/tree-sitter-vimdoc.git 2 | ; commit: 2249c44ecd3f5cf22da3dcccfb74f816ddb29245 3 | ; json from: tree-sitter-vimdoc/src/grammar.json 4 | ; From /tmp/tslua/vimdoc0.json 5 | ; EBNF to generate grammar.js at 6 | ; https://mingodad.github.io/lua-wasm-playground/ 7 | ; based on https://github.com/eatkins/tree-sitter-ebnf-generator 8 | ; see also https://mingodad.github.io/plgh/json2ebnf.html 9 | 10 | 11 | extras ::= { 12 | /[\t ]/ 13 | } 14 | 15 | conflicts ::= { 16 | { _line_noli _column_heading } 17 | { _column_heading } 18 | } 19 | 20 | rules: 21 | 22 | help_file ::= _blank* block* modeline* 23 | 24 | _atom ::= word 25 | | _atom_common 26 | 27 | word ::= @( -1( /[^,(\[\n\t ]+/ ) ) 28 | | _word_common 29 | 30 | _atom_noli ::= word_noli -> word 31 | | _atom_common 32 | 33 | word_noli ::= @( -1( /[^-•\n\t ][^(\[\n\t ]*/ ) ) 34 | | @( -1( /[-•][^\n\t ]+/ ) ) 35 | | _word_common 36 | 37 | _atom_common ::= tag 38 | | url 39 | | optionlink 40 | | taglink 41 | | codespan 42 | | argument 43 | | keycode 44 | | note 45 | 46 | _word_common ::= '*' 47 | | "'" 48 | | "'" !( /[^'\n\t ]/ ) 49 | | "'" !( /[a-z]*[^'a-z\n\t ][a-z]*/ ) !( "'" )? 50 | | "'" !( /[^'\n\t ]/ ) !( "'" ) 51 | | /\|\|+/ 52 | | '|' 53 | | '{' 54 | | '{}' 55 | | /\{\{+[0-9]*/ 56 | | '(' 57 | | '[' 58 | | '~' 59 | | '>' 60 | | ',' 61 | 62 | note ::= 'Note:' 63 | | 'NOTE:' 64 | | 'Notes:' 65 | | 'Warning:' 66 | | 'WARNING:' 67 | | 'Deprecated' 68 | | 'DEPRECATED:' 69 | 70 | keycode ::= /<[-a-zA-Z0-9_]+>/ 71 | | /<[SCMAD]-.>/ 72 | | /CTRL-./ 73 | | /CTRL-SHIFT-./ 74 | | /CTRL-(Break|PageUp|PageDown|Insert|Del)/ 75 | | 'CTRL-{char}' 76 | | /META-./ 77 | | /ALT-./ 78 | 79 | uppercase_name ::= !( /[A-Z0-9.()][-A-Z0-9.()_]+/ ) /[A-Z0-9.()][-A-Z0-9.()_]+/* 80 | 81 | _uppercase_words ::= <-1( !( /[A-Z0-9.()][-A-Z0-9.()_]+/ ) -> word /[A-Z0-9.()][-A-Z0-9.()_]+/* -> word ) 82 | 83 | block ::= ( line+ | line_li+ | line+ line_li+ ) ( !( '<' ) | _blank ) _blank* 84 | 85 | codeblock ::= >0( '>' ( !( /[a-z0-9]+\n/ ) -> language | !( /\n/ ) ) ( line_code -> line )+ -> code ) 86 | 87 | _blank ::= /\n/:blank 88 | 89 | line ::= column_heading 90 | | h1 91 | | h2 92 | | h3 93 | | codeblock 94 | | _line_noli 95 | 96 | line_li ::= >1( !( '<' )? /[-•][ ]+/ ( ( _atom+ /\n/ ) -> line | _atom+ -> line codeblock ) ( _line_noli -> line )* ) 97 | 98 | line_code ::= /\n/ 99 | | /[\t ]+[^\n]+\n/ 100 | 101 | _line_noli ::= ( _atom_noli | _uppercase_words ) _atom* ( codeblock | /\n/ ) 102 | 103 | modeline ::= @( 2( /vim:[^\n]+\n/ ) ) 104 | 105 | column_heading ::= _column_heading -> heading '~' -> delimiter !( /\n/ ) 106 | 107 | _column_heading ::= ~1( ( _atom_noli | _uppercase_words ) _atom* ) 108 | 109 | h1 ::= 1( !( /============+[\t ]*\n/ ) -> delimiter _atom+ -> heading ( tag _atom* )? /\n/ ) 110 | 111 | h2 ::= 1( !( /------------+[\t ]*\n/ ) -> delimiter _atom+ -> heading ( tag _atom* )? /\n/ ) 112 | 113 | h3 ::= uppercase_name -> heading ( tag _atom* )? /\n/ 114 | 115 | tag ::= '*' ( !( 1( /[^*\n\t ]+/ ) ) -> word ):text !( '*' ) 116 | 117 | url_word ::= /https?:[^\n\t)\] ]+/ 118 | 119 | url ::= ( url_word -> word ):text 120 | 121 | optionlink ::= "'" ( !( /[a-z][a-z]+/ ) -> word ):text !( "'" ) 122 | 123 | taglink ::= '|' ( !( 1( /[^|\n\t ]+/ ) ) -> word ):text !( '|' ) 124 | 125 | codespan ::= '`' ( !( /[^``\n]+/ ) -> word ):text !( '`' ) 126 | 127 | argument ::= '{' ( !( /[^}\n\t ]+/ ) -> word ):text !( '}' ) !( '?' )? 128 | 129 | -------------------------------------------------------------------------------- /examples/zig.ebnf: -------------------------------------------------------------------------------- 1 | ; repository: https://github.com/GrayJack/tree-sitter-zig.git 2 | ; commit: 8e970cb01c22cf89b8f70231ed4eca8d6fad1d56 3 | ; json from: tree-sitter-zig/src/grammar.json 4 | ; From /tmp/tslua/zig0.json 5 | ; EBNF to generate grammar.js at 6 | ; https://mingodad.github.io/lua-wasm-playground/ 7 | ; based on https://github.com/eatkins/tree-sitter-ebnf-generator 8 | ; see also https://mingodad.github.io/plgh/json2ebnf.html 9 | 10 | 11 | extras ::= { 12 | /\s/ 13 | line_comment 14 | doc_comment 15 | } 16 | 17 | conflicts ::= { 18 | { optional_type unary_operator } 19 | { array_type array_expression } 20 | { anonymous_struct_enum anonymous_array_expr } 21 | { assignment_expression } 22 | { call_expression } 23 | { parameter _expression } 24 | } 25 | 26 | rules: 27 | 28 | source_file ::= _statement* 29 | 30 | doc_comment ::= @( '///' /.*/ ) 31 | 32 | line_comment ::= @( '//' /.*/ ) 33 | 34 | _any ::= _statement 35 | | _expression 36 | 37 | _statement ::= _expression_statement 38 | | _declaration_statement 39 | 40 | _expression_statement ::= <0( _expression ';' | 1( _expression_ending_with_block ) ) 41 | 42 | _expression_ending_with_block ::= 1( block | comptime_block | defer_block | suspend_block | resume_block | if_expression | while_expression | for_expression | test_expression ) 43 | 44 | _declaration_statement ::= empty_statement 45 | | assignment_statement 46 | | function_signature 47 | | function_declaration 48 | 49 | _expression ::= <0( build_in_call_expr | call_expression | await_expression | suspend_expression | resume_expression | index_expression | field_expression | _expression_ending_with_block | struct_expression | struct_construction | anonymous_struct_enum | enum_expression | union_expression | error_expression | switch_expression | continue_expression | break_expression | return_expression | assignment_expression | array_expression | anonymous_array_expr | compound_assignment_expr | payload_expression | unary_expression | binary_expression | reference_expression | dereference_expression | orelse_postfix_expression | try_expression | _range_pattern | unreachable_expression | usingnamespace_expression | defer_expression | _type | _literals | identifier ) 50 | 51 | empty_statement ::= ';' 52 | 53 | assignment_statement ::= visibility_modifier? ( ( 'threadlocal' | 'comptime' ) -> assignment_modifier )? ( 'const' | 'var' ) identifier:name ( ':' _type:type )? '=' _expression:expression ';' 54 | 55 | function_signature ::= visibility_modifier? function_modifiers? 'fn' identifier:name parameters:parameters ( _expression:return )? ';' 56 | 57 | function_declaration ::= visibility_modifier? function_modifiers? 'fn' identifier:name parameters:parameters ( _expression:return )? block:body 58 | 59 | visibility_modifier ::= 'pub' 60 | 61 | function_modifiers ::= 'export' 62 | | 'stdcallcc' 63 | | 'nakedcc' 64 | | 'inline' 65 | | extern_modifier 66 | 67 | extern_modifier ::= 'extern' string_literal? 68 | 69 | parameters ::= '(' ( parameter ( ',' parameter )* ','? )? ')' 70 | 71 | parameter ::= 'comptime'? identifier:name ':' ( _type | 'anytype' -> inference_type | variadic_parameter | _expression ):type 72 | 73 | variadic_parameter ::= '...' 74 | 75 | build_in_call_expr ::= 14( ( /@[a-zA-Zα-ωΑ-Ωµ_][a-zA-Zα-ωΑ-Ωµ\d_]*/ -> identifier ):function arguments:arguments ) 76 | 77 | call_expression ::= 14( ( 'async' -> call_modifier )? identifier:function arguments:arguments ) 78 | 79 | await_expression ::= <0( 'await' _expression ) 80 | 81 | suspend_expression ::= <0( 'suspend' _expression? ) 82 | 83 | resume_expression ::= <0( 'resume' _expression? ) 84 | 85 | arguments ::= '(' ( _expression ( ',' _expression )* ','? )? ')' 86 | 87 | field_expression ::= <14( _expression:value '.' ( identifier -> field_identifier | _expression ):field ) 88 | 89 | index_expression ::= 14( _expression '[' ( _expression | slice_pattern ) ']' ) 90 | 91 | _pattern ::= slice_pattern 92 | | _range_pattern 93 | | field_expression -> field_pattern 94 | | _literals -> literal_pattern 95 | 96 | slice_pattern ::= >14( ( _expression:start )? ( '..' | '...' ) ( _expression:end )? ) 97 | 98 | _range_pattern ::= range_pattern_inclusive 99 | | range_pattern_exclusive 100 | 101 | range_pattern_inclusive ::= >0( _expression:start '...' _expression:end ) 102 | 103 | range_pattern_exclusive ::= >0( _expression:start '..' ( _expression:end )? ) 104 | 105 | switch_expression ::= 'switch' '(' _expression:value ')' switch_block:body 106 | 107 | switch_block ::= '{' ( switch_arm* switch_last_arm )? '}' 108 | 109 | switch_arm ::= switch_pattern:pattern '=>' ( _expression:value ',' | 1( _expression_ending_with_block ) :value ) 110 | 111 | switch_last_arm ::= ( 'else' -> else_switch | switch_pattern ):pattern '=>' _expression:value ','? 112 | 113 | switch_pattern ::= _pattern 114 | | _pattern ( ',' _pattern )* ','? 115 | 116 | if_expression ::= <0( 'if' _condition ( _expression | block ):consequence _else_tail? ) 117 | 118 | while_expression ::= <0( loop_label? ( 'inline' -> loop_modifier )? 'while' ( _condition | _condition_with_continue ) block:body _else_tail? ) 119 | 120 | for_expression ::= <0( loop_label? ( 'inline' -> loop_modifier )? 'for' _condition block:body _else_tail? ) 121 | 122 | _condition ::= <0( '(' _expression:condition ')' payload? ) 123 | 124 | _condition_with_continue ::= '(' _expression:condition ')' ':' '(' ( _expression | '{' _expression ( ';' _expression )* ';'? '}' ):continue ')' 125 | 126 | _else_tail ::= -1( 'else' _else_case ) 127 | 128 | _else_case ::= <2( ( _expression | block | if_expression | payload_expression ):alternative ) 129 | 130 | loop_label ::= ( identifier -> label_identifier ):name ':' 131 | 132 | payload ::= '|' '*'? ( identifier -> payload_identifier ( ',' identifier -> payload_identifier )* ','? ):values '|' 133 | 134 | payload_expression ::= <0( payload ( _expression | block ) ) 135 | 136 | break_expression ::= <0( 'break' ( loop_label_inverse:label )? ( _expression:value )? ) 137 | 138 | continue_expression ::= 'continue' ( loop_label_inverse:label )? 139 | 140 | loop_label_inverse ::= ':' ( identifier -> label_identifier ):name 141 | 142 | return_expression ::= <0( 'return' _expression ) 143 | | -1( 'return' ) 144 | 145 | test_expression ::= 'test' string_literal:test_name block:body 146 | 147 | try_expression ::= <0( 'try' _expression:expression ) 148 | 149 | usingnamespace_expression ::= <0( visibility_modifier? 'usingnamespace' _expression:import ) 150 | 151 | _type ::= -1( primitive_type | optional_type | pointer_type | error_type | array_type | custom_number_type | _struct_standalone -> struct_expression | identifier -> type_identifier ) 152 | 153 | primitive_type ::= 'i8' 154 | | 'u8' 155 | | 'i16' 156 | | 'u16' 157 | | 'i32' 158 | | 'u32' 159 | | 'i64' 160 | | 'u64' 161 | | 'i128' 162 | | 'u128' 163 | | 'isize' 164 | | 'usize' 165 | | 'c_short' 166 | | 'c_ushort' 167 | | 'c_int' 168 | | 'c_uint' 169 | | 'c_long' 170 | | 'c_ulong' 171 | | 'c_longlong' 172 | | 'c_ulonglong' 173 | | 'c_longdouble' 174 | | 'c_void' 175 | | 'f16' 176 | | 'f32' 177 | | 'f64' 178 | | 'f128' 179 | | 'comptime_int' 180 | | 'comptime_float' 181 | | 'bool' 182 | | 'void' 183 | | 'noreturn' 184 | | 'type' 185 | | 'anyerror' 186 | 187 | custom_number_type ::= /[iu]\d+/ 188 | 189 | error_type ::= <0( _type:err '!' _type:ok ) 190 | 191 | optional_type ::= -2( '?' _type ) 192 | 193 | array_type ::= -3( ( '[' ( integer_literal | identifier | ( '*' 'c'? ) -> pointer )?:size ']' )* type_prefix*? ( primitive_type | optional_type | pointer_type | error_type | custom_number_type | identifier -> type_identifier ) ) 194 | 195 | pointer_type ::= <0( '*' type_prefix*? _expression ) 196 | 197 | type_prefix ::= -1( 'null' | 'const' | 'volatile' | 'allowzero' | 'align' '(' _expression ')' | 'promise' '-' ) 198 | 199 | defer_expression ::= <0( ( 'defer' | 'errdefer' ) _expression ) 200 | 201 | comptime_block ::= 'comptime' block 202 | 203 | defer_block ::= ( 'defer' | 'errdefer' ) block 204 | 205 | suspend_block ::= 'suspend' block 206 | 207 | resume_block ::= 'resume' block 208 | 209 | block ::= <0( ( loop_label:label )? '{' _statement*? _expression? '}' ) 210 | 211 | reference_expression ::= 12( '&' _expression:value ) 212 | 213 | dereference_expression ::= _expression:value '.*' 214 | 215 | orelse_postfix_expression ::= _expression:value '.?' 216 | 217 | struct_construction ::= identifier -> type_identifier '{' ( field_init ( ',' field_init )* ','? )?:field '}' 218 | 219 | anonymous_struct_enum ::= '.{' ( field_init ( ',' field_init )* ','? ):field '}' 220 | 221 | field_init ::= '.' ( identifier -> field_identifier ):name '=' _expression:value 222 | 223 | union_expression ::= ( ( 'packed' | 'extern' ) -> union_modifier )? 'union' ( '(' ( _type | 'enum' -> inference_type ):type ')' )? '{' ( union_field_variant ( ',' union_field_variant )* ','? )?:field_variant _statement*? '}' 224 | 225 | union_field_variant ::= 2( ( identifier -> union_identifier ):name ( ':' ( _type | 'var' -> inference_type ):type )? ) 226 | 227 | enum_expression ::= ( ( 'packed' | 'extern' ) -> enum_modifier )? 'enum' ( '(' _type:type ')' )? '{' ( variant_declaration ( ',' variant_declaration )* ','? )?:variant _statement*? '}' 228 | 229 | variant_declaration ::= 2( ( identifier -> enum_identifier ):name ( '=' _expression:default )? ) 230 | 231 | struct_expression ::= ( ( 'packed' | 'extern' ) -> struct_modifier )? _struct_standalone 232 | 233 | _struct_standalone ::= 'struct' '{' ( field_declaration ( ',' field_declaration )* ','? )?:field _statement*? '}' 234 | 235 | field_declaration ::= <0( visibility_modifier? ( identifier -> field_identifier ):name ':' ( _type | 'var' -> inference_type ):type ( '=' _expression:default )? ) 236 | 237 | error_expression ::= 'error' ( _error_one_shorthand | _default_error ) 238 | 239 | _error_one_shorthand ::= '.' ( identifier -> error_identifier ):error_variant 240 | 241 | _default_error ::= '{' ( identifier -> error_identifier ( ',' identifier -> error_identifier )* ','? )?:error_variant '}' 242 | 243 | array_expression ::= ( '[' ( integer_literal | identifier ):size ']' )* _type:type array_values:values 244 | 245 | anonymous_array_expr ::= '.{' ( ( _expression ( ',' _expression )* ','? )? -> array_values ):values '}' 246 | 247 | array_values ::= '{' ( _expression ( ',' _expression )* ','? )? '}' 248 | 249 | assignment_expression ::= <0( ( 'defer' | 'errdefer' )? _expression:left '=' _expression:right ) 250 | 251 | compound_assignment_expr ::= <0( _expression:left assignment_operator:operator _expression:right ) 252 | 253 | unary_expression ::= <12( unary_operator:operator _expression:expression ) 254 | 255 | unreachable_expression ::= 'unreachable' 256 | 257 | binary_expression ::= <3( _expression:left ( 'and' -> binary_operator ):operator _expression:right ) 258 | | <2( _expression:left ( 'or' -> binary_operator ):operator _expression:right ) 259 | | <7( _expression:left ( '&' -> binary_operator ):operator _expression:right ) 260 | | <5( _expression:left ( '|' -> binary_operator ):operator _expression:right ) 261 | | <6( _expression:left ( '^' -> binary_operator ):operator _expression:right ) 262 | | <4( _expression:left ( ( '==' | '!=' | '<' | '<=' | '>' | '>=' ) -> binary_operator ):operator _expression:right ) 263 | | <8( _expression:left ( ( '<<' | '>>' ) -> binary_operator ):operator _expression:right ) 264 | | <9( _expression:left ( ( '+' | '-' | '++' | '+%' | '-%' ) -> binary_operator ):operator _expression:right ) 265 | | <10( _expression:left ( ( '*' | '/' | '%' | '**' | '*%' | '||' ) -> binary_operator ):operator _expression:right ) 266 | | <1( _expression:left ( ( 'orelse' | 'catch' ) -> binary_operator ):operator _expression:right ) 267 | 268 | _literals ::= integer_literal 269 | | float_literal 270 | | boolean_literal 271 | | null_literal 272 | | undefined_literal 273 | | char_literal 274 | | string_literal 275 | | multiline_string_literal 276 | | enum_literal 277 | 278 | enum_literal ::= >0( '.' ( identifier -> enum_identifier ):variant ) 279 | 280 | integer_literal ::= @( ( /[0-9]+/ | /0x[0-9a-fA-F]+/ | /0b[01]+/ | /0o[0-7]+/ ) ) 281 | 282 | float_literal ::= <0( @( ( /0[xX]/ /[0-9a-fA-F][0-9a-fA-F_]*/ '.' /[0-9a-fA-F][0-9a-fA-F_]*/ | /[0-9][0-9_]*/ '.' /[0-9][0-9_]*/ ) /[eEpP][+-]?\d+/? ) ) 283 | 284 | char_literal ::= "'" ( escape_sequence | /./ )? "'" 285 | 286 | string_literal ::= '"' ( escape_sequence | /[^"\\]+/ )* !( '"' ) 287 | 288 | multiline_string_literal ::= <0( ( '\\\\' ( /[^\r\n]/ | escape_sequence )* -> string_literal )+ ) 289 | 290 | escape_sequence ::= !( '\\' ( /[^xu\n]/ | /u[0-9a-fA-F]{4}/ | /u\{[0-9a-fA-F]+\}/ | /x[0-9a-fA-F]{2}/ ) ) 291 | 292 | boolean_literal ::= 'true' 293 | | 'false' 294 | 295 | null_literal ::= 'null' 296 | 297 | undefined_literal ::= 'undefined' 298 | 299 | assignment_operator ::= '+=' 300 | | '-=' 301 | | '*=' 302 | | '/=' 303 | | '+%=' 304 | | '-%=' 305 | | '*%=' 306 | | '%=' 307 | | '&=' 308 | | '|=' 309 | | '^=' 310 | | '<<=' 311 | | '>>=' 312 | 313 | unary_operator ::= '~' 314 | | '!' 315 | | '-' 316 | | '-%' 317 | 318 | identifier ::= _str_identifier 319 | | _identifier_text 320 | 321 | _str_identifier ::= '@"' ( escape_sequence | /[^"\\]+/ )* -> string_literal !( '"' ) 322 | 323 | _identifier_text ::= /[a-zA-Zα-ωΑ-Ωµ_][a-zA-Zα-ωΑ-Ωµ\d_]*/ 324 | 325 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Lua Playground 5 | 6 | 7 | 8 |
9 |
10 |
    11 |
  • 12 |
  • Lua Source Code
  • 13 |
  • 14 |
      15 |
    • 16 | 19 |
    • 20 |
    21 |
  • 22 |
23 |
{{syntax}}
24 |
25 |
26 |
27 |
    28 |
  • 29 |
  • Input Text (arg[1])
  • 30 |
  • 31 | 37 |
  • 38 |
39 |
{{source}}
40 |
Output
41 |
42 | 43 |
44 |
45 |
46 |
47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /lua-playground.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | EM_JS(void, switch_output, (const char* which), { 8 | output = UTF8ToString(which); 9 | }) 10 | 11 | EM_JS(void, set_result, (const char* which, int value), { 12 | result_name = UTF8ToString(which); 13 | result[result_name] = value; 14 | }) 15 | 16 | /* 17 | ** Message handler used to run all chunks 18 | */ 19 | static int msghandler (lua_State *L) { 20 | const char *msg = lua_tostring(L, 1); 21 | if (msg == NULL) { /* is error object not a string? */ 22 | if (luaL_callmeta(L, 1, "__tostring") && /* does it have a metamethod */ 23 | lua_type(L, -1) == LUA_TSTRING) /* that produces a string? */ 24 | return 1; /* that is the message */ 25 | else 26 | msg = lua_pushfstring(L, "(error object is a %s value)", 27 | luaL_typename(L, 1)); 28 | } 29 | luaL_traceback(L, L, msg, 1); /* append a standard traceback */ 30 | return 1; /* return the traceback */ 31 | } 32 | 33 | int run_lua(const char *script, const char *input) 34 | { 35 | //use of Javascript string.length can't be used for utf8 36 | size_t script_size = strlen(script); 37 | size_t input_size = strlen(input); 38 | int err = 0; // currently, zero is always returned; result codes for each part 39 | // are sent to JS via set_result() 40 | 41 | // default result values (-1 indicates we didn't reach a part) 42 | int compile_result = -1; 43 | int run_result = -1; 44 | int ast_result = -1; 45 | int profile_result = -1; 46 | 47 | lua_State* lua = luaL_newstate(); 48 | luaL_openlibs(lua); 49 | #ifdef WITH_LPEGLABEL 50 | luaL_requiref(lua, "lpeglabel", luaopen_lpeglabel, 1); 51 | lua_pop(lua, 1); /* remove lib */ 52 | #endif 53 | lua_pushcfunction(lua, msghandler); 54 | 55 | switch_output("compile_status"); 56 | 57 | lua_newtable(lua); 58 | lua_pushlstring(lua, input, input_size); 59 | lua_rawseti (lua, -2, 1); 60 | lua_setglobal(lua, "arg"); 61 | 62 | compile_result = luaL_loadbuffer(lua, script, script_size, "@source.lua"); 63 | 64 | if(compile_result == LUA_OK) { 65 | switch_output("run_status"); 66 | run_result = lua_pcall(lua, 0, LUA_MULTRET, lua_gettop(lua) - 1); 67 | if(run_result != LUA_OK) { 68 | switch_output("compile_status"); 69 | printf("%s\n", lua_tostring(lua, -1)); 70 | } 71 | } 72 | else { 73 | printf("%s\n", lua_tostring(lua, -1)); 74 | } 75 | 76 | lua_close(lua); 77 | set_result("compile", compile_result); 78 | set_result("run", run_result); 79 | set_result("ast", ast_result); 80 | set_result("profile", profile_result); 81 | return err; 82 | } 83 | -------------------------------------------------------------------------------- /mk-lua-amalgamation.lua: -------------------------------------------------------------------------------- 1 | local lua_51 = [==[ 2 | lapi.c 3 | lauxlib.c 4 | lbaselib.c 5 | lcode.c 6 | ldblib.c 7 | ldebug.c 8 | ldo.c 9 | ldump.c 10 | lfunc.c 11 | lgc.c 12 | linit.c 13 | liolib.c 14 | llex.c 15 | lmathlib.c 16 | lmem.c 17 | loadlib.c 18 | lobject.c 19 | lopcodes.c 20 | loslib.c 21 | lparser.c 22 | lstate.c 23 | lstring.c 24 | lstrlib.c 25 | ltable.c 26 | ltablib.c 27 | ltm.c 28 | lundump.c 29 | lvm.c 30 | lzio.c 31 | print.c 32 | bitlib.c 33 | ]==] 34 | 35 | local lua_52 = [==[ 36 | lapi.c 37 | lcode.c 38 | lctype.c 39 | ldebug.c 40 | ldo.c 41 | ldump.c 42 | lfunc.c 43 | lgc.c 44 | llex.c 45 | lmem.c 46 | lobject.c 47 | lopcodes.c 48 | lparser.c 49 | lstate.c 50 | lstring.c 51 | ltable.c 52 | ltm.c 53 | lundump.c 54 | lvm.c 55 | lzio.c 56 | lauxlib.c 57 | lbaselib.c 58 | lbitlib.c 59 | lcorolib.c 60 | ldblib.c 61 | liolib.c 62 | lmathlib.c 63 | loslib.c 64 | lstrlib.c 65 | ltablib.c 66 | loadlib.c 67 | linit.c 68 | ]==] 69 | 70 | local lua_53 = [==[ 71 | lapi.c 72 | lcode.c 73 | lctype.c 74 | ldebug.c 75 | ldo.c 76 | ldump.c 77 | lfunc.c 78 | lgc.c 79 | llex.c 80 | lmem.c 81 | lobject.c 82 | lopcodes.c 83 | lparser.c 84 | lstate.c 85 | lstring.c 86 | ltable.c 87 | ltm.c 88 | lundump.c 89 | lvm.c 90 | lzio.c 91 | lauxlib.c 92 | lbaselib.c 93 | lbitlib.c 94 | lcorolib.c 95 | ldblib.c 96 | liolib.c 97 | lmathlib.c 98 | loslib.c 99 | lstrlib.c 100 | ltablib.c 101 | lutf8lib.c 102 | loadlib.c 103 | linit.c 104 | ]==] 105 | 106 | local lua_54 = [==[ 107 | lapi.c 108 | lcode.c 109 | lctype.c 110 | ldebug.c 111 | ldo.c 112 | ldump.c 113 | lfunc.c 114 | lgc.c 115 | llex.c 116 | lmem.c 117 | lobject.c 118 | lopcodes.c 119 | lparser.c 120 | lstate.c 121 | lstring.c 122 | ltable.c 123 | ltm.c 124 | lundump.c 125 | lvm.c 126 | lzio.c 127 | lauxlib.c 128 | lbaselib.c 129 | lcorolib.c 130 | ldblib.c 131 | liolib.c 132 | lmathlib.c 133 | loadlib.c 134 | loslib.c 135 | lstrlib.c 136 | ltablib.c 137 | lutf8lib.c 138 | linit.c 139 | ]==] 140 | 141 | local lpeglabel_prefix = "/home/mingo/dev/lua/lpeglabel/" 142 | local lpeglabel = [==[ 143 | lplvm.c 144 | lplcap.c 145 | lpltree.c 146 | lplcode.c 147 | lplprint.c 148 | ]==] 149 | 150 | local included = {} 151 | local inc_sys = {} 152 | local inc_sys_count = 0 153 | local out = io.stdout 154 | 155 | function CopyWithInline(prefix, filename) 156 | if included[filename] then return end 157 | included[filename] = true 158 | print('//--Start of', filename); 159 | --if(filename:match("luac?.c")) 160 | local inp = assert(io.open(prefix .. filename, "r")) 161 | for line in inp:lines() do 162 | if line:match('#define LUA_USE_READLINE') then 163 | out:write("//" .. line .. "\n") 164 | else 165 | local inc = line:match('#include%s+(["<].-)[">]') 166 | if inc then 167 | out:write("//" .. line .. "\n") 168 | if inc:sub(1,1) == '"' then 169 | CopyWithInline(prefix, inc:sub(2)) 170 | else 171 | local fn = inc:sub(2) 172 | if inc_sys[fn] == null then 173 | inc_sys_count = inc_sys_count +1 174 | inc_sys[fn] = inc_sys_count 175 | end 176 | end 177 | else 178 | out:write(line .. "\n") 179 | end 180 | end 181 | end 182 | print('//--End of', filename); 183 | end 184 | 185 | print([==[ 186 | #include "cosmopolitan.h" 187 | #define loslib_c 188 | #define lua_c 189 | #define lobject_c 190 | #define LUA_USE_MKSTEMP 191 | #define LUA_USE_POSIX 192 | ]==]) 193 | 194 | --local prefix = '/home/mingo/dev/lua/lua-5.1.5/src/'; local lua_files = lua_51; 195 | --local prefix = '/home/mingo/dev/lua/lua-5.2.4/src/'; local lua_files = lua_52; 196 | --local prefix = '/home/mingo/dev/lua/lua-5.3.6/src/'; local lua_files = lua_53; 197 | --local prefix = '/home/mingo/dev/lua/lua-5.4.4/src/'; local lua_files = lua_54; 198 | local prefix = '/home/mingo/dev/lua/lua-5.4.6/src/'; local lua_files = lua_54; 199 | --for filename in lua_files:gmatch('#include "([^"]+)"') do 200 | for filename in lua_files:gmatch('([^\n]+)') do 201 | CopyWithInline(prefix, filename); 202 | end 203 | print('#ifdef WITH_LPEGLABEL') 204 | print('#define Instruction Instruction_lpeg') 205 | print('#define match match_lpeg') 206 | print('#define utf8_decode utf8_decode_lpeg') 207 | print('#define finaltarget finaltarget_lpeg') 208 | print('#define codenot codenot_lpeg') 209 | for filename in lpeglabel:gmatch('([^\n]+)') do 210 | CopyWithInline(lpeglabel_prefix, filename); 211 | end 212 | print('#undef codenot') 213 | print('#undef finaltarget') 214 | print('#undef utf8_decode') 215 | print('#undef match') 216 | print('#undef Instruction') 217 | print('#endif //WITH_LPEGLABEL'); 218 | print('#ifdef MAKE_LUA_CMD'); 219 | CopyWithInline(prefix, "lua.c"); 220 | print('#endif //MAKE_LUA_CMD'); 221 | print('#ifdef MAKE_LUAC_CMD'); 222 | CopyWithInline(prefix, "luac.c"); 223 | print('#endif //MAKE_LUAC_CMD'); 224 | print('#ifdef MAKE_LUA_WASM'); 225 | CopyWithInline("./", "lua-playground.c"); 226 | print('#endif //MAKE_LUA_WASM'); 227 | for k, v in pairs(inc_sys) do print("#include <" .. k .. "> //" .. v ) end -------------------------------------------------------------------------------- /mk-wasm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | destFolder=./ 3 | srcFolder=$PWD 4 | emsdk-env emcc \ 5 | -Os -DMAKE_LUA_WASM -DLUA_PROGNAME='"lua"' \ 6 | -DLUA_COMPAT_5_3 -DLUA_USE_LINUX -D_XOPEN_SOURCE=500 \ 7 | -DWITH_LPEGLABEL \ 8 | -o am-lua-5.4.6.js am-lua-5.4.6.c \ 9 | -sEXPORTED_FUNCTIONS=_run_lua -sEXPORTED_RUNTIME_METHODS=ccall,cwrap \ 10 | -sALLOW_MEMORY_GROWTH -s TOTAL_STACK=8MB \ 11 | --embed-file $HOME/dev/lua/lpeglabel/relabel.lua@$destFolder \ 12 | --embed-file $HOME/dev/lua/lpegrex/lpegrex.lua@$destFolder 13 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | margin: 0; 4 | padding: 0; 5 | text-decoration: none; 6 | list-style: none; 7 | } 8 | body { 9 | display: flex; 10 | flex-direction: column; 11 | height: 100vh; 12 | } 13 | #main { 14 | flex: 1; 15 | display: none; 16 | z-index: 0; 17 | } 18 | .editor-container { 19 | flex: 1; 20 | width: 100%; 21 | display: flex; 22 | flex-direction: column; 23 | margin: 6px; 24 | } 25 | .editor-container:first-child { 26 | margin-right: 0; 27 | } 28 | .editor-header { 29 | display: flex; 30 | margin: 0 2px; 31 | } 32 | .editor-header > li { 33 | height: 32px; 34 | line-height: 24px; 35 | } 36 | .editor-header > li > span { 37 | margin-right: 6px; 38 | } 39 | .editor-options { 40 | margin-left: auto; 41 | } 42 | .editor-header-options { 43 | display: flex; 44 | } 45 | .validation { 46 | display: inline-block; 47 | height: 20px; 48 | width: 20px; 49 | margin: 2px 0; 50 | border-radius: 50%; 51 | background-color: lightgreen; 52 | } 53 | .validation-invalid { 54 | background-color: pink; 55 | } 56 | .option { 57 | margin-right: 8px; 58 | } 59 | .option:last-child { 60 | margin-right: 0; 61 | } 62 | .option input[type=checkbox] { 63 | margin-right: 4px; 64 | } 65 | .option .parse { 66 | padding-left: 8px; 67 | padding-right: 8px; 68 | height: 24px; 69 | cursor: pointer; 70 | } 71 | .editor-area { 72 | flex: 1; 73 | border: 1px solid lightgray; 74 | } 75 | .editor-info { 76 | margin-top: 6px; 77 | height: 160px; 78 | border: 1px solid lightgray; 79 | padding: 8px; 80 | overflow-y: auto; 81 | } 82 | .editor-info li[data-ln] { 83 | cursor: pointer; 84 | } 85 | .editor-info li[data-ln]:hover{ 86 | background-color: lightyellow; 87 | } 88 | .editor-sub-header { 89 | padding: 4px; 90 | } 91 | .show-toggle { 92 | margin-right: 6px; 93 | } 94 | #overlay { 95 | position: absolute; 96 | width: 100vw; 97 | height: 100vh; 98 | cursor: wait; 99 | display: none; 100 | z-index: -1; 101 | } 102 | --------------------------------------------------------------------------------