const {pythonCode, sep1} = require('./python');
module.exports = grammar({
name: 'bitbake',
conflicts: $ => [
[$.primary_expression, $.pattern],
[$.primary_expression, $.list_splat_pattern],
[$.tuple, $.tuple_pattern],
[$.list, $.list_pattern],
[$.with_item, $._collection_elements],
[$.named_expression, $.as_pattern],
[$.print_statement, $.primary_expression],
[$.function_definition, $.primary_expression],
],
externals: $ => [
$._newline,
$._indent,
$._dedent,
$.string_start,
$._string_content,
$.escape_interpolation,
$.string_end,
$.comment,
']',
')',
'}',
],
extras: $ => [
/\s/,
$.comment,
],
inline: $ => [
$._simple_statement,
$._compound_statement,
$._suite,
$._expressions,
$._left_hand_side,
$.keyword_identifier,
],
supertypes: $ => [
$._simple_statement,
$._compound_statement,
$.expression,
$.primary_expression,
$.pattern,
$.parameter,
],
rules: {
recipe: $ => repeat(seq(
choice(
$.variable_assignment,
$.unset_statement,
$.inherit_directive,
$.include_directive,
$.require_directive,
$.export_statement,
$.overrides_statement,
$.export_functions_statement,
$.addtask_statement,
$.deltask_statement,
$.addhandler_statement,
$.anonymous_python_function,
$.function_definition,
$.python_function_definition,
),
choice(/\r?\n/, '\0'),
)),
variable_assignment: $ => seq(
$.identifier,
optional(choice(
$.variable_flag,
$.variable_expansion,
$.override,
)),
field('operator',
choice(
'=',
'?=',
'??=',
':=',
'+=',
'=+',
'.=',
'=.',
),
),
$.literal,
),
variable_flag: $ => seq(
'[',
choice(
alias($.identifier, $.flag),
'noexec',
),
']',
),
override: $ => seq(
':',
sep1(choice('append', 'prepend', 'remove', $.identifier), ':'),
),
unset_statement: $ => seq(
'unset',
$.identifier,
optional($.variable_flag),
),
inherit_directive: $ => seq(
'inherit',
repeat1(choice(
$.variable_expansion,
$.inline_python,
$.inherit_path,
)),
),
inherit_path: _ => /[^$ \r\n][^ \r\n]+/,
inherit_configuration_directive: $ => seq(
'INHERIT',
'+=',
'"',
sep1($.identifier, ' '),
'"',
),
include_directive: $ => seq(
'include',
alias(/[^ \r\n]+/, $.include_path),
),
require_directive: $ => seq(
'require',
alias(/[^ \r\n]+/, $.include_path),
),
export_statement: $ => seq(
'export',
choice($.identifier, $.variable_assignment),
),
overrides_statement: $ => seq(
'OVERRIDES',
'=',
'"',
sep1($.identifier, ':'),
'"',
),
export_functions_statement: $ => seq(
'EXPORT_FUNCTIONS',
repeat1($.identifier),
),
addtask_statement: $ => seq(
'addtask',
$.identifier,
optional(choice(
seq(
'after',
repeat1($.identifier),
'before',
repeat1($.identifier),
),
seq(
'before',
repeat1($.identifier),
'after',
repeat1($.identifier),
),
)),
),
deltask_statement: $ => seq(
'deltask',
$.identifier,
),
addhandler_statement: $ => seq(
'addhandler',
$.identifier,
),
anonymous_python_function: $ => seq(
'python',
optional(seq(
$.identifier,
optional($.override),
)),
'(',
')',
'{',
$._suite,
'}',
),
function_definition: $ => seq(
$.identifier,
optional($.override),
'(',
')',
'{',
alias(/(?:({[^}]*})|[^}])*/, $.shell_content),
'}',
),
literal: $ => choice(
$.string,
$.identifier,
),
string: $ => choice(
seq(
'"',
repeat(choice(
alias(token.immediate(prec(1, /([^"$\\]|\\.?|\\?\r?\n)+/)), $.string_content),
$.variable_expansion,
$.inline_python,
'$BB_ENV_PASSTHROUGH',
'$BB_ENV_PASSTHROUGH_ADDITIONS',
)),
'"',
),
seq(
'\'',
repeat(choice(
alias(token.immediate(prec(1, /([^'$\\]|\\?\r?\n)+/)), $.string_content),
$.variable_expansion,
$.inline_python,
'$BB_ENV_PASSTHROUGH',
'$BB_ENV_PASSTHROUGH_ADDITIONS',
)),
'\'',
),
),
inline_python: $ => seq('${@', $.expression, '}'),
variable_expansion: $ => seq('${', optional($.identifier), '}'),
identifier: _ => /[a-zA-Z0-9_-]+/,
comment: _ => token(seq('#', /.*/)),
...pythonCode,
},
});