They cause super inconsistent parsing behaviour if they show up pretty much anywhere else because there is no difference between an implicit tuple and a set of comma-separated parameters.
664 lines
12 KiB
EBNF
664 lines
12 KiB
EBNF
start
|
|
=
|
|
expressions
|
|
$
|
|
;
|
|
|
|
expressions
|
|
=
|
|
{expression}*
|
|
;
|
|
|
|
expression
|
|
=
|
|
| content
|
|
| raw_block_expression
|
|
| block_expression
|
|
| line_block_expression
|
|
| variable_expression
|
|
| comment_expression
|
|
| line_comment_expression
|
|
;
|
|
|
|
raw_block_expression
|
|
=
|
|
raw_block_start
|
|
raw:{ !raw_block_end CHAR }*
|
|
raw_block_end
|
|
;
|
|
|
|
raw_block_start
|
|
=
|
|
block_open "raw" {SP}* block_close
|
|
;
|
|
|
|
raw_block_end
|
|
=
|
|
block_open "endraw" {SP}* block_close
|
|
;
|
|
|
|
block_expression
|
|
=
|
|
| block_expression_pair
|
|
| block_expression_single
|
|
;
|
|
|
|
block_expression_pair
|
|
=
|
|
start:block_start contents:expressions end:block_end
|
|
;
|
|
|
|
block_expression_single
|
|
=
|
|
block:block_start
|
|
;
|
|
|
|
block_start
|
|
=
|
|
block_open !("end") name:IDENTIFIER [ "(" name_call_parameters:variable_accessor_call_parameters ")" ]
|
|
[ {SP}+ parameters:block_parameters ]
|
|
{SP}* block_close
|
|
;
|
|
|
|
block_end
|
|
=
|
|
block_open "end" name:IDENTIFIER {SP}* block_close
|
|
;
|
|
|
|
block_open
|
|
=
|
|
| ( {SP}* block_open_symbol "-" {SP}* )
|
|
| block_open_symbol {SP}*
|
|
;
|
|
|
|
block_open_symbol
|
|
=
|
|
"{%"
|
|
;
|
|
|
|
block_close
|
|
=
|
|
| ( "-" block_close_symbol {SP}* )
|
|
| block_close_symbol
|
|
;
|
|
|
|
block_close_symbol
|
|
=
|
|
"%}"
|
|
;
|
|
|
|
line_block_expression
|
|
=
|
|
| line_block_expression_pair
|
|
| line_block_expression_single
|
|
;
|
|
|
|
line_block_expression_pair
|
|
=
|
|
start:line_block_start contents:expressions end:line_block_end
|
|
;
|
|
|
|
line_block_expression_single
|
|
=
|
|
block:line_block_start
|
|
;
|
|
|
|
line_block_start
|
|
=
|
|
line_block_open !("end") name:IDENTIFIER { !"\n" SP}* parameters:[ line_block_parameters ] [ { !"\n" SP }* ":" ] line_block_close
|
|
;
|
|
|
|
line_block_end
|
|
=
|
|
line_block_open "end" name:IDENTIFIER line_block_close
|
|
;
|
|
|
|
line_block_open
|
|
=
|
|
{ !"\n" SP }* line_block_open_symbol { !"\n" SP }*
|
|
;
|
|
|
|
line_block_open_symbol
|
|
=
|
|
"#"
|
|
;
|
|
|
|
line_block_close
|
|
=
|
|
| ( {SP}* $ )
|
|
| ( { !"\n" SP }* "\n" )
|
|
;
|
|
|
|
line_block_parameters
|
|
=
|
|
@+:block_parameter { { !"\n" SP }+ @+:block_parameter }*
|
|
;
|
|
|
|
block_parameters
|
|
=
|
|
@+:block_parameter
|
|
{
|
|
block_parameter_separator
|
|
@+:block_parameter
|
|
}*
|
|
;
|
|
|
|
block_parameter_separator
|
|
=
|
|
| ( {SP}* "," {SP}* )
|
|
| ( {SP}+ )
|
|
;
|
|
|
|
block_parameter
|
|
=
|
|
| block_parameter_key_value
|
|
| block_parameter_value_only
|
|
;
|
|
|
|
block_parameter_key_value
|
|
=
|
|
key:block_parameter_key {SP}* "=" {SP}* value:variable_accessor_call_parameter_value
|
|
;
|
|
|
|
block_parameter_key
|
|
=
|
|
variable_accessor_call_parameter_key
|
|
;
|
|
|
|
block_parameter_value_only
|
|
=
|
|
| value:variable_identifier_with_alias
|
|
| value:variable_accessor_call_parameter_value
|
|
| value:conditional_expression
|
|
;
|
|
|
|
variable_expression
|
|
=
|
|
variable_open type:`variable` name:variable_expression_name variable_close
|
|
;
|
|
|
|
variable_open
|
|
=
|
|
| ( {SP}* variable_open_symbol "-" {SP}* )
|
|
| ( variable_open_symbol {SP}* )
|
|
;
|
|
|
|
variable_open_symbol
|
|
=
|
|
"{{"
|
|
;
|
|
|
|
variable_close
|
|
=
|
|
| ( {SP}* "-" variable_close_symbol {SP}* )
|
|
| ( {SP}* variable_close_symbol )
|
|
;
|
|
|
|
variable_close_symbol
|
|
=
|
|
"}}"
|
|
;
|
|
|
|
variable_expression_name
|
|
=
|
|
| TUPLE_LITERAL
|
|
| conditional_expression
|
|
;
|
|
|
|
variable_identifier
|
|
=
|
|
| variable_identifier_parentheses
|
|
| variable_identifier_raw
|
|
;
|
|
|
|
variable_identifier_parentheses
|
|
=
|
|
"(" @:conditional_expression ")"
|
|
;
|
|
|
|
variable_identifier_raw
|
|
=
|
|
[ signed:( "-" | "+" ) ]
|
|
variable:( LITERAL | IDENTIFIER )
|
|
accessors:{ variable_accessor }*
|
|
{ {SP}* filters+:variable_filter }*
|
|
;
|
|
|
|
variable_identifier_with_alias
|
|
=
|
|
variable:IDENTIFIER
|
|
{SP}* "as" {SP}*
|
|
alias:IDENTIFIER
|
|
;
|
|
|
|
variable_accessor
|
|
=
|
|
| variable_accessor_brackets
|
|
| variable_accessor_call
|
|
| variable_accessor_dot
|
|
;
|
|
|
|
variable_accessor_brackets
|
|
=
|
|
accessor_type:`brackets`
|
|
"[" parameter:variable_identifier "]"
|
|
;
|
|
|
|
variable_accessor_call
|
|
=
|
|
accessor_type:`call`
|
|
"(" parameters:[variable_accessor_call_parameters] ")"
|
|
;
|
|
|
|
variable_accessor_dot
|
|
=
|
|
accessor_type:`dot`
|
|
"." parameter:( IDENTIFIER | NUMBER_LITERAL )
|
|
;
|
|
|
|
variable_accessor_call_parameters
|
|
=
|
|
@+:variable_accessor_call_parameter
|
|
{ {SP}* "," {SP}* @+:variable_accessor_call_parameter }*
|
|
;
|
|
|
|
variable_accessor_call_parameter
|
|
=
|
|
| variable_accessor_call_parameter_key_value
|
|
| variable_accessor_call_parameter_value_only
|
|
| variable_accessor_call_parameter_vararg
|
|
| variable_accessor_call_parameter_varkwarg
|
|
;
|
|
|
|
variable_accessor_call_parameter_vararg
|
|
=
|
|
"*" dynamic_argument:variable_identifier
|
|
;
|
|
|
|
variable_accessor_call_parameter_varkwarg
|
|
=
|
|
"**" dynamic_keyword_argument:variable_identifier
|
|
;
|
|
|
|
variable_accessor_call_parameter_key_value
|
|
=
|
|
key:variable_accessor_call_parameter_key {SP}* "=" {SP}* value:variable_accessor_call_parameter_value
|
|
;
|
|
|
|
variable_accessor_call_parameter_value_only
|
|
=
|
|
value:variable_accessor_call_parameter_value
|
|
;
|
|
|
|
variable_accessor_call_parameter_key
|
|
=
|
|
IDENTIFIER
|
|
;
|
|
|
|
variable_accessor_call_parameter_value
|
|
=
|
|
conditional_expression
|
|
;
|
|
|
|
conditional_expression
|
|
=
|
|
| conditional_expression_not
|
|
| conditional_expression_if
|
|
| conditional_expression_logical
|
|
| conditional_expression_operator
|
|
| conditional_expression_test
|
|
| complex_expression
|
|
| variable_identifier
|
|
| conditional_expression_parentheses
|
|
;
|
|
|
|
complex_expression
|
|
=
|
|
| complex_expression_powers
|
|
| complex_expression_math2
|
|
| concatenate_expression
|
|
| complex_expression_math1
|
|
| complex_expression_parentheses
|
|
| variable_identifier
|
|
;
|
|
|
|
complex_expression_powers
|
|
=
|
|
left:variable_identifier {SP}* math_operator:"**" {SP}* right:variable_identifier
|
|
;
|
|
|
|
complex_expression_math2
|
|
=
|
|
left:variable_identifier
|
|
{SP}* math_operator:complex_expression_math2_operations {SP}*
|
|
right:variable_identifier
|
|
;
|
|
|
|
complex_expression_math2_operations
|
|
=
|
|
| "*"
|
|
| "/"
|
|
| "//"
|
|
| "%"
|
|
;
|
|
|
|
complex_expression_math1
|
|
=
|
|
left:variable_identifier
|
|
{SP}* math_operator:complex_expression_math1_operations {SP}*
|
|
right:complex_expression
|
|
;
|
|
|
|
complex_expression_math1_operations
|
|
=
|
|
| "+"
|
|
| "-"
|
|
;
|
|
|
|
complex_expression_parentheses
|
|
=
|
|
"(" {SP}*
|
|
complex_expression
|
|
{SP}* ")"
|
|
;
|
|
|
|
conditional_expression_parentheses
|
|
=
|
|
"(" {SP}* @:conditional_expression {SP}* ")"
|
|
;
|
|
|
|
conditional_expression_not
|
|
=
|
|
"not" {SP}+ not:conditional_expression
|
|
;
|
|
|
|
conditional_expression_if
|
|
=
|
|
true_value:variable_identifier
|
|
{SP}* "if" {SP}*
|
|
test_expression:conditional_expression
|
|
[ {SP}* "else" {SP}* false_value:conditional_expression ]
|
|
;
|
|
|
|
conditional_expression_logical
|
|
=
|
|
left:conditional_expression
|
|
{SP}* logical_operator:variable_tests_logical_operator {SP}*
|
|
right:conditional_expression
|
|
;
|
|
|
|
conditional_expression_operator
|
|
=
|
|
conditional_expression_operator_in
|
|
| (
|
|
left:complex_expression
|
|
{SP}* operator:conditional_expression_operator_operations {SP}*
|
|
right:conditional_expression
|
|
)
|
|
;
|
|
|
|
conditional_expression_operator_in
|
|
=
|
|
| (
|
|
"not"
|
|
left:variable_identifier
|
|
{SP}* operator:`"notin"` "in" {SP}*
|
|
right:variable_identifier
|
|
)
|
|
| (
|
|
left:variable_identifier
|
|
{SP}+
|
|
(
|
|
| ( "not" {SP}* "in" operator:`"notin"` )
|
|
| operator:"in"
|
|
)
|
|
{SP}+
|
|
right:variable_identifier
|
|
)
|
|
;
|
|
|
|
conditional_expression_test
|
|
=
|
|
test_variable:variable_identifier
|
|
{SP}* "is"
|
|
[ {SP}+ "not" {SP} negated:`True` ]
|
|
{SP}*
|
|
test_function:variable_identifier
|
|
[
|
|
{SP}*
|
|
!( (variable_tests_logical_operator | "is" | "else" ) {SP}* )
|
|
test_function_parameter:variable_identifier
|
|
]
|
|
;
|
|
|
|
conditional_expression_operator_operations
|
|
=
|
|
| "=="
|
|
| "!="
|
|
| ">"
|
|
| ">="
|
|
| "<"
|
|
| "<="
|
|
;
|
|
|
|
variable_tests_logical_operator
|
|
=
|
|
| "and"
|
|
| "or"
|
|
;
|
|
|
|
concatenate_expression
|
|
=
|
|
concatenate+:variable_identifier
|
|
{ {SP}* "~" {SP}* concatenate+:variable_identifier }+
|
|
;
|
|
|
|
variable_filter
|
|
=
|
|
"|" {SP}* @:filter
|
|
;
|
|
filter =
|
|
variable:IDENTIFIER
|
|
accessors:{ variable_accessor_call }*
|
|
;
|
|
|
|
comment_expression
|
|
=
|
|
comment_open comment:comment_content comment_close
|
|
;
|
|
|
|
comment_open =
|
|
comment_open_symbol
|
|
;
|
|
|
|
comment_open_symbol
|
|
=
|
|
"{#"
|
|
;
|
|
|
|
comment_close
|
|
=
|
|
comment_close_symbol
|
|
;
|
|
|
|
comment_close_symbol
|
|
=
|
|
"#}"
|
|
;
|
|
|
|
comment_content
|
|
=
|
|
{ !comment_close CHAR }*
|
|
;
|
|
|
|
line_comment_expression
|
|
=
|
|
line_comment_open comment:line_comment_content &"\n"
|
|
;
|
|
|
|
line_comment_open
|
|
=
|
|
{SP}* line_comment_open_symbol
|
|
;
|
|
|
|
line_comment_open_symbol
|
|
=
|
|
'##'
|
|
;
|
|
|
|
line_comment_content
|
|
=
|
|
{ !"\n" CHAR }*
|
|
;
|
|
|
|
content
|
|
=
|
|
!(
|
|
| line_block_open
|
|
| block_open
|
|
| variable_open
|
|
| comment_open
|
|
| line_comment_open
|
|
) CHAR ;
|
|
|
|
LITERAL
|
|
=
|
|
| NONE_LITERAL
|
|
| STRING_LITERAL
|
|
| NUMBER_LITERAL
|
|
| BOOLEAN_LITERAL
|
|
| DICTIONARY_LITERAL
|
|
| LIST_LITERAL
|
|
| EXPLICIT_TUPLE_LITERAL
|
|
;
|
|
|
|
DICTIONARY_LITERAL
|
|
=
|
|
literal_type:`dictionary`
|
|
(
|
|
| ( "{" {SP}* value+:dictionary_key_value { {SP}* "," {SP}* value+:dictionary_key_value } {SP}* "}" )
|
|
| ( "{" {SP}* "}" )
|
|
)
|
|
;
|
|
|
|
dictionary_key_value
|
|
=
|
|
key:STRING_LITERAL {SP}* ":" {SP}* value:variable_identifier
|
|
;
|
|
|
|
LIST_LITERAL
|
|
=
|
|
literal_type:`list`
|
|
(
|
|
| ( "[" {SP}* value+:variable_identifier {SP}* { "," {SP}* value+:variable_identifier }* {SP}* "]" )
|
|
| ( "[" {SP}* "]" )
|
|
)
|
|
;
|
|
|
|
TUPLE_LITERAL
|
|
=
|
|
| EXPLICIT_TUPLE_LITERAL
|
|
| IMPLICIT_TUPLE_LITERAL
|
|
| EMPTY_TUPLE_LITERAL
|
|
;
|
|
|
|
EXPLICIT_TUPLE_LITERAL
|
|
=
|
|
literal_type:`tuple`
|
|
"(" value:TUPLE_LITERAL_CONTENTS ")"
|
|
;
|
|
|
|
IMPLICIT_TUPLE_LITERAL
|
|
=
|
|
literal_type:`tuple`
|
|
value:TUPLE_LITERAL_CONTENTS
|
|
;
|
|
|
|
TUPLE_LITERAL_CONTENTS
|
|
=
|
|
| ( @+:variable_identifier {SP}* { "," {SP}* @+:variable_identifier {SP}* }+ )
|
|
| ( @+:variable_identifier {SP}* "," {SP}* )
|
|
;
|
|
|
|
EMPTY_TUPLE_LITERAL
|
|
=
|
|
literal_type:`tuple`
|
|
"(" {SP}* ")"
|
|
;
|
|
|
|
INTEGER_LITERAL
|
|
=
|
|
/[\d_]*\d+/
|
|
;
|
|
|
|
SIGNED_INTEGER_LITERAL
|
|
=
|
|
/[+-]?[\d_]*\d+/
|
|
;
|
|
|
|
NUMBER_LITERAL
|
|
=
|
|
literal_type:`number`
|
|
whole:INTEGER_LITERAL
|
|
[ "." fractional:INTEGER_LITERAL ]
|
|
[ ( "e" | "E" ) exponent:SIGNED_INTEGER_LITERAL ]
|
|
;
|
|
|
|
STRING_LITERAL
|
|
=
|
|
| STRING_LITERAL_SINGLE_QUOTE
|
|
| STRING_LITERAL_DOUBLE_QUOTE
|
|
;
|
|
|
|
STRING_LITERAL_SINGLE_QUOTE
|
|
=
|
|
literal_type:`string`
|
|
"'" value:{ !"'" /./ }* "'"
|
|
;
|
|
|
|
STRING_LITERAL_DOUBLE_QUOTE
|
|
=
|
|
literal_type:`string`
|
|
'"' value:{ !'"' /./ }* '"'
|
|
;
|
|
|
|
BOOLEAN_LITERAL
|
|
=
|
|
literal_type:`boolean`
|
|
(
|
|
| ( ("true" | "True") value:`True`)
|
|
| ( ("false" | "False") value:`False`)
|
|
)
|
|
;
|
|
|
|
NONE_LITERAL
|
|
=
|
|
literal_type:`none`
|
|
( "none" | "None" ) value:`None`
|
|
;
|
|
|
|
IDENTIFIER
|
|
=
|
|
/[a-zA-Z_][a-zA-Z0-9_]*/
|
|
;
|
|
|
|
ALPHA
|
|
=
|
|
/[a-zA-Z]/
|
|
;
|
|
|
|
DIGIT
|
|
=
|
|
/[0-9]/
|
|
;
|
|
|
|
SP
|
|
=
|
|
/\s/
|
|
;
|
|
|
|
CHAR
|
|
=
|
|
| ?'.'
|
|
| ?'\s'
|
|
; |