diff --git a/generator/src/dbscheme.rs b/generator/src/dbscheme.rs new file mode 100644 index 00000000000..27078ce9717 --- /dev/null +++ b/generator/src/dbscheme.rs @@ -0,0 +1,195 @@ +use std::fmt; + +/// Represents a distinct entry in the database schema. +pub enum Entry { + /// An entry defining a database table. + Table(Table), + + /// An entry defining type that is a union of other types. + Union(Union), +} + +/// A table in the database schema. +pub struct Table { + pub name: String, + pub columns: Vec, + pub keysets: Option>, +} + +/// A union in the database schema. +pub struct Union { + pub name: String, + pub members: Vec, +} + +/// A column in a table. +pub struct Column { + pub db_type: DbColumnType, + pub name: String, + pub unique: bool, + pub ql_type: QlColumnType, + pub ql_type_is_ref: bool, +} + +/// The database column type. +pub enum DbColumnType { + Int, + String, +} + +// The QL type of a column. +pub enum QlColumnType { + /// Primitive `int` type. + Int, + + /// Primitive `string` type. + String, + + /// A custom type, defined elsewhere by a table or union. + Custom(String), +} + +const RESERVED_KEYWORDS: [&'static str; 14] = [ + "boolean", "case", "date", "float", "int", "key", "of", "order", "ref", "string", "subtype", + "type", "unique", "varchar", +]; + +/// Returns a string that's a copy of `name` but suitably escaped to be a valid +/// QL identifier. +pub fn escape_name(name: &str) -> String { + let mut result = String::new(); + + // If there's a leading underscore, replace it with 'underscore_'. + if let Some(c) = name.chars().next() { + if c == '_' { + result.push_str("underscore"); + } + } + for c in name.chars() { + match c { + '{' => result.push_str("lbrace"), + '}' => result.push_str("rbrace"), + '<' => result.push_str("langle"), + '>' => result.push_str("rangle"), + '[' => result.push_str("lbracket"), + ']' => result.push_str("rbracket"), + '(' => result.push_str("lparen"), + ')' => result.push_str("rparen"), + '|' => result.push_str("pipe"), + '=' => result.push_str("equal"), + '~' => result.push_str("tilde"), + '?' => result.push_str("question"), + '`' => result.push_str("backtick"), + '^' => result.push_str("caret"), + '!' => result.push_str("bang"), + '#' => result.push_str("hash"), + '%' => result.push_str("percent"), + '&' => result.push_str("ampersand"), + '.' => result.push_str("dot"), + ',' => result.push_str("comma"), + '/' => result.push_str("slash"), + ':' => result.push_str("colon"), + ';' => result.push_str("semicolon"), + '"' => result.push_str("dquote"), + '*' => result.push_str("star"), + '+' => result.push_str("plus"), + '-' => result.push_str("minus"), + '@' => result.push_str("at"), + _ => result.push_str(&c.to_lowercase().to_string()), + } + } + + for &keyword in &RESERVED_KEYWORDS { + if result == keyword { + result.push_str("__"); + break; + } + } + + result +} + +impl fmt::Display for Table { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if let Some(keyset) = &self.keysets { + write!(f, "#keyset[")?; + for (key_index, key) in keyset.iter().enumerate() { + if key_index > 0 { + write!(f, ", ")?; + } + write!(f, "{}", key)?; + } + write!(f, "]\n")?; + } + + write!(f, "{}(\n", self.name)?; + for (column_index, column) in self.columns.iter().enumerate() { + write!(f, " ")?; + if column.unique { + write!(f, "unique ")?; + } + write!( + f, + "{} ", + match column.db_type { + DbColumnType::Int => "int", + DbColumnType::String => "string", + } + )?; + write!(f, "{}: ", column.name)?; + match &column.ql_type { + QlColumnType::Int => write!(f, "int")?, + QlColumnType::String => write!(f, "string")?, + QlColumnType::Custom(name) => write!(f, "@{}", name)?, + } + if column.ql_type_is_ref { + write!(f, " ref")?; + } + if column_index + 1 != self.columns.len() { + write!(f, ",")?; + } + write!(f, "\n")?; + } + write!(f, ");")?; + + Ok(()) + } +} + +impl fmt::Display for Union { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "@{} = ", self.name)?; + let mut first = true; + for member in &self.members { + if first { + first = false; + } else { + write!(f, " | ")?; + } + write!(f, "@{}", member)?; + } + Ok(()) + } +} + +/// Generates the dbscheme by writing the given dbscheme `entries` to the `file`. +pub fn write( + language_name: &str, + file: &mut dyn std::io::Write, + entries: &[Entry], +) -> std::io::Result<()> { + write!(file, "// CodeQL database schema for {}\n", language_name)?; + write!( + file, + "// Automatically generated from the tree-sitter grammar; do not edit\n\n" + )?; + + for entry in entries { + match entry { + Entry::Table(table) => write!(file, "{}\n\n", table)?, + Entry::Union(union) => write!(file, "{}\n\n", union)?, + } + } + + Ok(()) +} diff --git a/generator/src/language.rs b/generator/src/language.rs new file mode 100644 index 00000000000..7f289c27de2 --- /dev/null +++ b/generator/src/language.rs @@ -0,0 +1,7 @@ +use std::path::PathBuf; + +pub struct Language { + pub name: String, + pub node_types_path: PathBuf, + pub dbscheme_path: PathBuf, +} diff --git a/generator/src/main.rs b/generator/src/main.rs index 684368c2cfa..121865b7be8 100644 --- a/generator/src/main.rs +++ b/generator/src/main.rs @@ -1,3 +1,316 @@ -fn main() { - println!("generator"); +mod dbscheme; +mod language; +mod node_types; + +use language::Language; +use node_types::{FieldInfo, NodeInfo}; +use std::fs::File; +use std::io::LineWriter; +use std::path::PathBuf; + +/// Given a tree-sitter node type's (kind, named) pair, returns a single string +/// representing the (unescaped) name we'll use to refer to corresponding QL +/// type. +fn node_type_name(kind: &str, named: bool) -> String { + if named { + kind.to_string() + } else { + format!("{}_unnamed", kind) + } +} + +/// Given the name of the parent node, and its field information, returns the +/// name of the field's type. This may be an ad-hoc union of all the possible +/// types the field can take, in which case the union is added to `entries`. +fn make_field_type( + parent_name: &str, + field_name: &str, + field_info: &FieldInfo, + entries: &mut Vec, +) -> String { + if field_info.types.len() == 1 { + // This field can only have a single type. + let t = &field_info.types[0]; + dbscheme::escape_name(&node_type_name(&t.kind, t.named)) + } else { + // This field can have one of several types. Create an ad-hoc QL union + // type to represent them. + let field_union_name = format!("{}_{}_type", parent_name, field_name); + let field_union_name = dbscheme::escape_name(&field_union_name); + let mut members: Vec = Vec::new(); + for field_type in &field_info.types { + members.push(dbscheme::escape_name(&node_type_name( + &field_type.kind, + field_type.named, + ))); + } + entries.push(dbscheme::Entry::Union(dbscheme::Union { + name: field_union_name.clone(), + members, + })); + field_union_name + } +} + +/// Adds the appropriate dbscheme information for the given field, either as a +/// column on `main_table`, or as an auxiliary table. +fn add_field( + main_table: &mut dbscheme::Table, + parent_name: &str, + field_name: &str, + field_info: &FieldInfo, + entries: &mut Vec, +) { + if field_info.multiple || !field_info.required { + // This field can appear zero or multiple times, so put + // it in an auxiliary table. + let field_type = make_field_type(parent_name, field_name, field_info, entries); + let field_table = dbscheme::Table { + name: format!("{}_{}", parent_name, field_name), + columns: vec![ + // First column is a reference to the parent. + dbscheme::Column { + unique: false, + db_type: dbscheme::DbColumnType::Int, + name: dbscheme::escape_name(parent_name), + ql_type: dbscheme::QlColumnType::Custom(dbscheme::escape_name(parent_name)), + ql_type_is_ref: true, + }, + // Then an index column. + dbscheme::Column { + unique: false, + db_type: dbscheme::DbColumnType::Int, + name: "index".to_string(), + ql_type: dbscheme::QlColumnType::Int, + ql_type_is_ref: true, + }, + // And then the field + dbscheme::Column { + unique: true, + db_type: dbscheme::DbColumnType::Int, + name: field_type.clone(), + ql_type: dbscheme::QlColumnType::Custom(field_type), + ql_type_is_ref: true, + }, + ], + // In addition to the field being unique, the combination of + // parent+index is unique, so add a keyset for them. + keysets: Some(vec![ + dbscheme::escape_name(parent_name), + "index".to_string(), + ]), + }; + entries.push(dbscheme::Entry::Table(field_table)); + } else { + // This field must appear exactly once, so we add it as + // a column to the main table for the node type. + let field_type = make_field_type(parent_name, field_name, field_info, entries); + main_table.columns.push(dbscheme::Column { + unique: false, + db_type: dbscheme::DbColumnType::Int, + name: String::from(field_name), + ql_type: dbscheme::QlColumnType::Custom(field_type), + ql_type_is_ref: true, + }); + } +} + +/// Converts the given tree-sitter node types into CodeQL dbscheme entries. +fn convert_nodes(nodes: &[NodeInfo]) -> Vec { + let mut entries: Vec = Vec::new(); + let mut top_members: Vec = Vec::new(); + + for node in nodes { + if let Some(subtypes) = &node.subtypes { + // It's a tree-sitter supertype node, for which we create a union + // type. + let mut members: Vec = Vec::new(); + for subtype in subtypes { + members.push(dbscheme::escape_name(&node_type_name( + &subtype.kind, + subtype.named, + ))) + } + entries.push(dbscheme::Entry::Union(dbscheme::Union { + name: dbscheme::escape_name(&node_type_name(&node.kind, node.named)), + members, + })); + } else { + // It's a product type, defined by a table. + let name = node_type_name(&node.kind, node.named); + let mut main_table = dbscheme::Table { + name: dbscheme::escape_name(&(format!("{}_def", name))), + columns: vec![dbscheme::Column { + db_type: dbscheme::DbColumnType::Int, + name: "id".to_string(), + unique: true, + ql_type: dbscheme::QlColumnType::Custom(dbscheme::escape_name(&name)), + ql_type_is_ref: false, + }], + keysets: None, + }; + top_members.push(dbscheme::escape_name(&name)); + + let mut is_leaf = true; + + // If the type also has fields or children, then we create either + // auxiliary tables or columns in the defining table for them. + if let Some(fields) = &node.fields { + for (field_name, field_info) in fields { + is_leaf = false; + add_field(&mut main_table, &name, field_name, field_info, &mut entries); + } + } + if let Some(children) = &node.children { + is_leaf = false; + + // Treat children as if they were a field called 'child'. + add_field(&mut main_table, &name, "child", children, &mut entries); + } + + if is_leaf { + // There were no fields and no children, so it's a leaf node in + // the TS grammar. Add a column for the node text. + main_table.columns.push(dbscheme::Column { + unique: false, + db_type: dbscheme::DbColumnType::String, + name: "text".to_string(), + ql_type: dbscheme::QlColumnType::String, + ql_type_is_ref: true, + }); + } + + // Finally, the type's defining table also includes the location. + main_table.columns.push(dbscheme::Column { + unique: false, + db_type: dbscheme::DbColumnType::Int, + name: "loc".to_string(), + ql_type: dbscheme::QlColumnType::Custom("location".to_string()), + ql_type_is_ref: true, + }); + + entries.push(dbscheme::Entry::Table(main_table)); + } + } + + // Create a union of all database types. + entries.push(dbscheme::Entry::Union(dbscheme::Union { + name: "top".to_string(), + members: top_members, + })); + + entries +} + +fn write_dbscheme(language: &Language, entries: &[dbscheme::Entry]) -> std::io::Result<()> { + println!( + "Writing to '{}'", + match language.dbscheme_path.to_str() { + None => "", + Some(p) => p, + } + ); + let file = File::create(&language.dbscheme_path)?; + let mut file = LineWriter::new(file); + dbscheme::write(&language.name, &mut file, &entries) +} + +fn create_location_entry() -> dbscheme::Entry { + dbscheme::Entry::Table(dbscheme::Table { + name: "location".to_string(), + keysets: None, + columns: vec![ + dbscheme::Column { + unique: true, + db_type: dbscheme::DbColumnType::Int, + name: "id".to_string(), + ql_type: dbscheme::QlColumnType::Custom("location".to_string()), + ql_type_is_ref: false, + }, + dbscheme::Column { + unique: false, + db_type: dbscheme::DbColumnType::String, + name: "file_path".to_string(), + ql_type: dbscheme::QlColumnType::String, + ql_type_is_ref: true, + }, + dbscheme::Column { + unique: false, + db_type: dbscheme::DbColumnType::Int, + name: "start_line".to_string(), + ql_type: dbscheme::QlColumnType::Int, + ql_type_is_ref: true, + }, + dbscheme::Column { + unique: false, + db_type: dbscheme::DbColumnType::Int, + name: "start_column".to_string(), + ql_type: dbscheme::QlColumnType::Int, + ql_type_is_ref: true, + }, + dbscheme::Column { + unique: false, + db_type: dbscheme::DbColumnType::Int, + name: "end_line".to_string(), + ql_type: dbscheme::QlColumnType::Int, + ql_type_is_ref: true, + }, + dbscheme::Column { + unique: false, + db_type: dbscheme::DbColumnType::Int, + name: "end_column".to_string(), + ql_type: dbscheme::QlColumnType::Int, + ql_type_is_ref: true, + }, + ], + }) +} + +fn create_source_location_prefix_entry() -> dbscheme::Entry { + dbscheme::Entry::Table(dbscheme::Table { + name: "sourceLocationPrefix".to_string(), + keysets: None, + columns: vec![dbscheme::Column { + unique: false, + db_type: dbscheme::DbColumnType::String, + name: "prefix".to_string(), + ql_type: dbscheme::QlColumnType::String, + ql_type_is_ref: true, + }], + }) +} + +fn main() { + // TODO: figure out proper dbscheme output path and/or take it from the + // command line. + let ruby = Language { + name: "Ruby".to_string(), + node_types_path: PathBuf::from("tree-sitter-ruby/src/node-types.json"), + dbscheme_path: PathBuf::from("ruby.dbscheme"), + }; + match node_types::read(&ruby.node_types_path) { + Err(e) => { + println!( + "Failed to read '{}': {}", + match ruby.node_types_path.to_str() { + None => "", + Some(p) => p, + }, + e + ); + std::process::exit(1); + } + Ok(nodes) => { + let mut dbscheme_entries = convert_nodes(&nodes); + dbscheme_entries.push(create_location_entry()); + dbscheme_entries.push(create_source_location_prefix_entry()); + match write_dbscheme(&ruby, &dbscheme_entries) { + Err(e) => { + println!("Failed to write dbscheme: {}", e); + std::process::exit(2); + } + Ok(()) => {} + } + } + } } diff --git a/generator/src/node_types.rs b/generator/src/node_types.rs new file mode 100644 index 00000000000..f8c06f29c67 --- /dev/null +++ b/generator/src/node_types.rs @@ -0,0 +1,74 @@ +use serde::Deserialize; +use std::collections::BTreeMap; +use std::fmt; +use std::path::Path; + +#[derive(Deserialize)] +pub struct NodeInfo { + #[serde(rename = "type")] + pub kind: String, + pub named: bool, + #[serde(skip_serializing_if = "Option::is_none")] + pub fields: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub children: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub subtypes: Option>, +} + +#[derive(Deserialize)] +pub struct NodeType { + #[serde(rename = "type")] + pub kind: String, + pub named: bool, +} + +#[derive(Deserialize)] +pub struct FieldInfo { + pub multiple: bool, + pub required: bool, + pub types: Vec, +} + +impl Default for FieldInfo { + fn default() -> Self { + FieldInfo { + multiple: false, + required: true, + types: Vec::new(), + } + } +} + +pub enum Error { + IOError(std::io::Error), + JsonError(serde_json::error::Error), +} + +impl From for Error { + fn from(error: std::io::Error) -> Self { + Error::IOError(error) + } +} + +impl From for Error { + fn from(error: serde_json::Error) -> Self { + Error::JsonError(error) + } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Error::IOError(e) => write!(f, "{}", e), + Error::JsonError(e) => write!(f, "{}", e), + } + } +} + +/// Deserializes the node types from the JSON at the given `path`. +pub fn read(path: &Path) -> Result, Error> { + let json_data = std::fs::read_to_string(path)?; + let node_types: Vec = serde_json::from_str(&json_data)?; + Ok(node_types) +} diff --git a/ruby.dbscheme b/ruby.dbscheme new file mode 100644 index 00000000000..c0631bbb80b --- /dev/null +++ b/ruby.dbscheme @@ -0,0 +1,1864 @@ +// CodeQL database schema for Ruby +// Automatically generated from the tree-sitter grammar; do not edit + +@underscore_arg = @underscore_primary | @assignment | @binary | @conditional | @operator_assignment | @range | @unary + +@underscore_lhs = @underscore_variable | @call | @element_reference | @false | @method_call | @nil | @scope_resolution | @true + +@underscore_method_name = @class_variable | @constant | @global_variable | @identifier | @instance_variable | @operator | @setter | @symbol + +@underscore_primary = @underscore_lhs | @array | @begin | @break | @case__ | @chained_string | @character | @class | @complex | @float__ | @for | @hash | @heredoc_beginning | @if | @integer | @lambda | @method | @module | @next | @parenthesized_statements | @rational | @redo | @regex | @retry | @return | @singleton_class | @singleton_method | @string__ | @string_array | @subshell | @symbol | @symbol_array | @unary | @unless | @until | @while | @yield + +@underscore_statement = @underscore_arg | @alias | @assignment | @begin_block | @binary | @break | @call | @end_block | @if_modifier | @method_call | @next | @operator_assignment | @rescue_modifier | @return | @unary | @undef | @unless_modifier | @until_modifier | @while_modifier | @yield + +@underscore_variable = @class_variable | @constant | @global_variable | @identifier | @instance_variable | @self | @super + +alias_def( + unique int id: @alias, + int alias: @underscore_method_name ref, + int name: @underscore_method_name ref, + int loc: @location ref +); + +@argument_list_child_type = @underscore_arg | @block_argument | @break | @call | @hash_splat_argument | @method_call | @next | @pair | @return | @splat_argument | @yield + +#keyset[argument_list, index] +argument_list_child( + int argument_list: @argument_list ref, + int index: int ref, + unique int argument_list_child_type: @argument_list_child_type ref +); + +argument_list_def( + unique int id: @argument_list, + int loc: @location ref +); + +@array_child_type = @underscore_arg | @block_argument | @break | @call | @hash_splat_argument | @method_call | @next | @pair | @return | @splat_argument | @yield + +#keyset[array, index] +array_child( + int array: @array ref, + int index: int ref, + unique int array_child_type: @array_child_type ref +); + +array_def( + unique int id: @array, + int loc: @location ref +); + +@assignment_left_type = @underscore_lhs | @left_assignment_list + +@assignment_right_type = @underscore_arg | @break | @call | @method_call | @next | @return | @right_assignment_list | @splat_argument | @yield + +assignment_def( + unique int id: @assignment, + int left: @assignment_left_type ref, + int right: @assignment_right_type ref, + int loc: @location ref +); + +@bare_string_child_type = @escape_sequence | @interpolation + +#keyset[bare_string, index] +bare_string_child( + int bare_string: @bare_string ref, + int index: int ref, + unique int bare_string_child_type: @bare_string_child_type ref +); + +bare_string_def( + unique int id: @bare_string, + int loc: @location ref +); + +@bare_symbol_child_type = @escape_sequence | @interpolation + +#keyset[bare_symbol, index] +bare_symbol_child( + int bare_symbol: @bare_symbol ref, + int index: int ref, + unique int bare_symbol_child_type: @bare_symbol_child_type ref +); + +bare_symbol_def( + unique int id: @bare_symbol, + int loc: @location ref +); + +@begin_child_type = @underscore_statement | @else | @empty_statement | @ensure | @rescue + +#keyset[begin, index] +begin_child( + int begin: @begin ref, + int index: int ref, + unique int begin_child_type: @begin_child_type ref +); + +begin_def( + unique int id: @begin, + int loc: @location ref +); + +@begin_block_child_type = @underscore_statement | @empty_statement + +#keyset[begin_block, index] +begin_block_child( + int begin_block: @begin_block ref, + int index: int ref, + unique int begin_block_child_type: @begin_block_child_type ref +); + +begin_block_def( + unique int id: @begin_block, + int loc: @location ref +); + +@binary_left_type = @underscore_arg | @break | @call | @method_call | @next | @return | @yield + +@binary_operator_type = @bangequal_unnamed | @bangtilde_unnamed | @percent_unnamed | @ampersand_unnamed | @ampersandampersand_unnamed | @star_unnamed | @starstar_unnamed | @plus_unnamed | @minus_unnamed | @slash_unnamed | @langle_unnamed | @langlelangle_unnamed | @langleequal_unnamed | @langleequalrangle_unnamed | @equalequal_unnamed | @equalequalequal_unnamed | @equaltilde_unnamed | @rangle_unnamed | @rangleequal_unnamed | @ranglerangle_unnamed | @caret_unnamed | @and_unnamed | @or_unnamed | @pipe_unnamed | @pipepipe_unnamed + +@binary_right_type = @underscore_arg | @break | @call | @method_call | @next | @return | @yield + +binary_def( + unique int id: @binary, + int left: @binary_left_type ref, + int operator: @binary_operator_type ref, + int right: @binary_right_type ref, + int loc: @location ref +); + +@block_child_type = @underscore_statement | @block_parameters | @empty_statement + +#keyset[block, index] +block_child( + int block: @block ref, + int index: int ref, + unique int block_child_type: @block_child_type ref +); + +block_def( + unique int id: @block, + int loc: @location ref +); + +block_argument_def( + unique int id: @block_argument, + int child: @underscore_arg ref, + int loc: @location ref +); + +block_parameter_def( + unique int id: @block_parameter, + int name: @identifier ref, + int loc: @location ref +); + +@block_parameters_child_type = @block_parameter | @destructured_parameter | @hash_splat_parameter | @identifier | @keyword_parameter | @optional_parameter | @splat_parameter + +#keyset[block_parameters, index] +block_parameters_child( + int block_parameters: @block_parameters ref, + int index: int ref, + unique int block_parameters_child_type: @block_parameters_child_type ref +); + +block_parameters_def( + unique int id: @block_parameters, + int loc: @location ref +); + +#keyset[break, index] +break_child( + int break: @break ref, + int index: int ref, + unique int argument_list: @argument_list ref +); + +break_def( + unique int id: @break, + int loc: @location ref +); + +@call_method_type = @argument_list | @constant | @identifier | @operator + +@call_receiver_type = @underscore_primary | @method_call + +call_def( + unique int id: @call, + int method: @call_method_type ref, + int receiver: @call_receiver_type ref, + int loc: @location ref +); + +#keyset[case__, index] +case_value( + int case__: @case__ ref, + int index: int ref, + unique int underscore_statement: @underscore_statement ref +); + +@case_child_type = @else | @when + +#keyset[case__, index] +case_child( + int case__: @case__ ref, + int index: int ref, + unique int case_child_type: @case_child_type ref +); + +case_def( + unique int id: @case__, + int loc: @location ref +); + +#keyset[chained_string, index] +chained_string_child( + int chained_string: @chained_string ref, + int index: int ref, + unique int string__: @string__ ref +); + +chained_string_def( + unique int id: @chained_string, + int loc: @location ref +); + +@class_name_type = @constant | @scope_resolution + +@class_child_type = @underscore_statement | @else | @empty_statement | @ensure | @rescue | @superclass + +#keyset[class, index] +class_child( + int class: @class ref, + int index: int ref, + unique int class_child_type: @class_child_type ref +); + +class_def( + unique int id: @class, + int name: @class_name_type ref, + int loc: @location ref +); + +conditional_def( + unique int id: @conditional, + int alternative: @underscore_arg ref, + int condition: @underscore_arg ref, + int consequence: @underscore_arg ref, + int loc: @location ref +); + +@destructured_left_assignment_child_type = @underscore_lhs | @destructured_left_assignment | @rest_assignment + +#keyset[destructured_left_assignment, index] +destructured_left_assignment_child( + int destructured_left_assignment: @destructured_left_assignment ref, + int index: int ref, + unique int destructured_left_assignment_child_type: @destructured_left_assignment_child_type ref +); + +destructured_left_assignment_def( + unique int id: @destructured_left_assignment, + int loc: @location ref +); + +@destructured_parameter_child_type = @block_parameter | @destructured_parameter | @hash_splat_parameter | @identifier | @keyword_parameter | @optional_parameter | @splat_parameter + +#keyset[destructured_parameter, index] +destructured_parameter_child( + int destructured_parameter: @destructured_parameter ref, + int index: int ref, + unique int destructured_parameter_child_type: @destructured_parameter_child_type ref +); + +destructured_parameter_def( + unique int id: @destructured_parameter, + int loc: @location ref +); + +@do_child_type = @underscore_statement | @empty_statement + +#keyset[do, index] +do_child( + int do: @do ref, + int index: int ref, + unique int do_child_type: @do_child_type ref +); + +do_def( + unique int id: @do, + int loc: @location ref +); + +@do_block_child_type = @underscore_statement | @block_parameters | @else | @empty_statement | @ensure | @rescue + +#keyset[do_block, index] +do_block_child( + int do_block: @do_block ref, + int index: int ref, + unique int do_block_child_type: @do_block_child_type ref +); + +do_block_def( + unique int id: @do_block, + int loc: @location ref +); + +@element_reference_child_type = @underscore_arg | @block_argument | @break | @call | @hash_splat_argument | @method_call | @next | @pair | @return | @splat_argument | @yield + +#keyset[element_reference, index] +element_reference_child( + int element_reference: @element_reference ref, + int index: int ref, + unique int element_reference_child_type: @element_reference_child_type ref +); + +element_reference_def( + unique int id: @element_reference, + int object: @underscore_primary ref, + int loc: @location ref +); + +#keyset[else, index] +else_condition( + int else: @else ref, + int index: int ref, + unique int semicolon_unnamed: @semicolon_unnamed ref +); + +@else_child_type = @underscore_statement | @empty_statement + +#keyset[else, index] +else_child( + int else: @else ref, + int index: int ref, + unique int else_child_type: @else_child_type ref +); + +else_def( + unique int id: @else, + int loc: @location ref +); + +@elsif_alternative_type = @else | @elsif + +#keyset[elsif, index] +elsif_alternative( + int elsif: @elsif ref, + int index: int ref, + unique int elsif_alternative_type: @elsif_alternative_type ref +); + +#keyset[elsif, index] +elsif_consequence( + int elsif: @elsif ref, + int index: int ref, + unique int then: @then ref +); + +elsif_def( + unique int id: @elsif, + int condition: @underscore_statement ref, + int loc: @location ref +); + +empty_statement_def( + unique int id: @empty_statement, + string text: string ref, + int loc: @location ref +); + +@end_block_child_type = @underscore_statement | @empty_statement + +#keyset[end_block, index] +end_block_child( + int end_block: @end_block ref, + int index: int ref, + unique int end_block_child_type: @end_block_child_type ref +); + +end_block_def( + unique int id: @end_block, + int loc: @location ref +); + +@ensure_child_type = @underscore_statement | @empty_statement + +#keyset[ensure, index] +ensure_child( + int ensure: @ensure ref, + int index: int ref, + unique int ensure_child_type: @ensure_child_type ref +); + +ensure_def( + unique int id: @ensure, + int loc: @location ref +); + +exception_variable_def( + unique int id: @exception_variable, + int child: @underscore_lhs ref, + int loc: @location ref +); + +@exceptions_child_type = @underscore_arg | @splat_argument + +#keyset[exceptions, index] +exceptions_child( + int exceptions: @exceptions ref, + int index: int ref, + unique int exceptions_child_type: @exceptions_child_type ref +); + +exceptions_def( + unique int id: @exceptions, + int loc: @location ref +); + +@for_pattern_type = @underscore_lhs | @destructured_left_assignment | @rest_assignment + +#keyset[for, index] +for_pattern( + int for: @for ref, + int index: int ref, + unique int for_pattern_type: @for_pattern_type ref +); + +for_def( + unique int id: @for, + int body: @do ref, + int value: @in ref, + int loc: @location ref +); + +@hash_child_type = @hash_splat_argument | @pair + +#keyset[hash, index] +hash_child( + int hash: @hash ref, + int index: int ref, + unique int hash_child_type: @hash_child_type ref +); + +hash_def( + unique int id: @hash, + int loc: @location ref +); + +hash_splat_argument_def( + unique int id: @hash_splat_argument, + int child: @underscore_arg ref, + int loc: @location ref +); + +#keyset[hash_splat_parameter, index] +hash_splat_parameter_name( + int hash_splat_parameter: @hash_splat_parameter ref, + int index: int ref, + unique int identifier: @identifier ref +); + +hash_splat_parameter_def( + unique int id: @hash_splat_parameter, + int loc: @location ref +); + +@if_alternative_type = @else | @elsif + +#keyset[if, index] +if_alternative( + int if: @if ref, + int index: int ref, + unique int if_alternative_type: @if_alternative_type ref +); + +#keyset[if, index] +if_consequence( + int if: @if ref, + int index: int ref, + unique int then: @then ref +); + +if_def( + unique int id: @if, + int condition: @underscore_statement ref, + int loc: @location ref +); + +@if_modifier_condition_type = @underscore_arg | @break | @call | @method_call | @next | @return | @yield + +if_modifier_def( + unique int id: @if_modifier, + int body: @underscore_statement ref, + int condition: @if_modifier_condition_type ref, + int loc: @location ref +); + +in_def( + unique int id: @in, + int child: @underscore_arg ref, + int loc: @location ref +); + +interpolation_def( + unique int id: @interpolation, + int child: @underscore_statement ref, + int loc: @location ref +); + +#keyset[keyword_parameter, index] +keyword_parameter_value( + int keyword_parameter: @keyword_parameter ref, + int index: int ref, + unique int underscore_arg: @underscore_arg ref +); + +keyword_parameter_def( + unique int id: @keyword_parameter, + int name: @identifier ref, + int loc: @location ref +); + +@lambda_body_type = @block | @do_block + +#keyset[lambda, index] +lambda_parameters( + int lambda: @lambda ref, + int index: int ref, + unique int lambda_parameters: @lambda_parameters ref +); + +lambda_def( + unique int id: @lambda, + int body: @lambda_body_type ref, + int loc: @location ref +); + +@lambda_parameters_child_type = @block_parameter | @destructured_parameter | @hash_splat_parameter | @identifier | @keyword_parameter | @optional_parameter | @splat_parameter + +#keyset[lambda_parameters, index] +lambda_parameters_child( + int lambda_parameters: @lambda_parameters ref, + int index: int ref, + unique int lambda_parameters_child_type: @lambda_parameters_child_type ref +); + +lambda_parameters_def( + unique int id: @lambda_parameters, + int loc: @location ref +); + +@left_assignment_list_child_type = @underscore_lhs | @destructured_left_assignment | @rest_assignment + +#keyset[left_assignment_list, index] +left_assignment_list_child( + int left_assignment_list: @left_assignment_list ref, + int index: int ref, + unique int left_assignment_list_child_type: @left_assignment_list_child_type ref +); + +left_assignment_list_def( + unique int id: @left_assignment_list, + int loc: @location ref +); + +#keyset[method, index] +method_parameters( + int method: @method ref, + int index: int ref, + unique int method_parameters: @method_parameters ref +); + +@method_child_type = @underscore_statement | @else | @empty_statement | @ensure | @rescue + +#keyset[method, index] +method_child( + int method: @method ref, + int index: int ref, + unique int method_child_type: @method_child_type ref +); + +method_def( + unique int id: @method, + int name: @underscore_method_name ref, + int loc: @location ref +); + +#keyset[method_call, index] +method_call_arguments( + int method_call: @method_call ref, + int index: int ref, + unique int argument_list: @argument_list ref +); + +@method_call_block_type = @block | @do_block + +#keyset[method_call, index] +method_call_block( + int method_call: @method_call ref, + int index: int ref, + unique int method_call_block_type: @method_call_block_type ref +); + +@method_call_method_type = @underscore_variable | @call | @scope_resolution + +method_call_def( + unique int id: @method_call, + int method: @method_call_method_type ref, + int loc: @location ref +); + +@method_parameters_child_type = @block_parameter | @destructured_parameter | @hash_splat_parameter | @identifier | @keyword_parameter | @optional_parameter | @splat_parameter + +#keyset[method_parameters, index] +method_parameters_child( + int method_parameters: @method_parameters ref, + int index: int ref, + unique int method_parameters_child_type: @method_parameters_child_type ref +); + +method_parameters_def( + unique int id: @method_parameters, + int loc: @location ref +); + +@module_name_type = @constant | @scope_resolution + +@module_child_type = @underscore_statement | @else | @empty_statement | @ensure | @rescue + +#keyset[module, index] +module_child( + int module: @module ref, + int index: int ref, + unique int module_child_type: @module_child_type ref +); + +module_def( + unique int id: @module, + int name: @module_name_type ref, + int loc: @location ref +); + +#keyset[next, index] +next_child( + int next: @next ref, + int index: int ref, + unique int argument_list: @argument_list ref +); + +next_def( + unique int id: @next, + int loc: @location ref +); + +operator_def( + unique int id: @operator, + string text: string ref, + int loc: @location ref +); + +@operator_assignment_right_type = @underscore_arg | @break | @call | @method_call | @next | @return | @yield + +operator_assignment_def( + unique int id: @operator_assignment, + int left: @underscore_lhs ref, + int right: @operator_assignment_right_type ref, + int loc: @location ref +); + +optional_parameter_def( + unique int id: @optional_parameter, + int name: @identifier ref, + int value: @underscore_arg ref, + int loc: @location ref +); + +@pair_key_type = @underscore_arg | @string__ | @symbol + +pair_def( + unique int id: @pair, + int key: @pair_key_type ref, + int value: @underscore_arg ref, + int loc: @location ref +); + +@parenthesized_statements_child_type = @underscore_statement | @empty_statement + +#keyset[parenthesized_statements, index] +parenthesized_statements_child( + int parenthesized_statements: @parenthesized_statements ref, + int index: int ref, + unique int parenthesized_statements_child_type: @parenthesized_statements_child_type ref +); + +parenthesized_statements_def( + unique int id: @parenthesized_statements, + int loc: @location ref +); + +@pattern_child_type = @underscore_arg | @splat_argument + +pattern_def( + unique int id: @pattern, + int child: @pattern_child_type ref, + int loc: @location ref +); + +@program_child_type = @underscore_statement | @empty_statement | @uninterpreted + +#keyset[program, index] +program_child( + int program: @program ref, + int index: int ref, + unique int program_child_type: @program_child_type ref +); + +program_def( + unique int id: @program, + int loc: @location ref +); + +#keyset[range, index] +range_child( + int range: @range ref, + int index: int ref, + unique int underscore_arg: @underscore_arg ref +); + +range_def( + unique int id: @range, + int loc: @location ref +); + +rational_def( + unique int id: @rational, + int child: @integer ref, + int loc: @location ref +); + +#keyset[redo, index] +redo_child( + int redo: @redo ref, + int index: int ref, + unique int argument_list: @argument_list ref +); + +redo_def( + unique int id: @redo, + int loc: @location ref +); + +@regex_child_type = @escape_sequence | @interpolation + +#keyset[regex, index] +regex_child( + int regex: @regex ref, + int index: int ref, + unique int regex_child_type: @regex_child_type ref +); + +regex_def( + unique int id: @regex, + int loc: @location ref +); + +#keyset[rescue, index] +rescue_body( + int rescue: @rescue ref, + int index: int ref, + unique int then: @then ref +); + +#keyset[rescue, index] +rescue_exceptions( + int rescue: @rescue ref, + int index: int ref, + unique int exceptions: @exceptions ref +); + +#keyset[rescue, index] +rescue_variable( + int rescue: @rescue ref, + int index: int ref, + unique int exception_variable: @exception_variable ref +); + +rescue_def( + unique int id: @rescue, + int loc: @location ref +); + +@rescue_modifier_handler_type = @underscore_arg | @break | @call | @method_call | @next | @return | @yield + +rescue_modifier_def( + unique int id: @rescue_modifier, + int body: @underscore_statement ref, + int handler: @rescue_modifier_handler_type ref, + int loc: @location ref +); + +#keyset[rest_assignment, index] +rest_assignment_child( + int rest_assignment: @rest_assignment ref, + int index: int ref, + unique int underscore_lhs: @underscore_lhs ref +); + +rest_assignment_def( + unique int id: @rest_assignment, + int loc: @location ref +); + +#keyset[retry, index] +retry_child( + int retry: @retry ref, + int index: int ref, + unique int argument_list: @argument_list ref +); + +retry_def( + unique int id: @retry, + int loc: @location ref +); + +#keyset[return, index] +return_child( + int return: @return ref, + int index: int ref, + unique int argument_list: @argument_list ref +); + +return_def( + unique int id: @return, + int loc: @location ref +); + +@right_assignment_list_child_type = @underscore_arg | @splat_argument + +#keyset[right_assignment_list, index] +right_assignment_list_child( + int right_assignment_list: @right_assignment_list ref, + int index: int ref, + unique int right_assignment_list_child_type: @right_assignment_list_child_type ref +); + +right_assignment_list_def( + unique int id: @right_assignment_list, + int loc: @location ref +); + +@scope_resolution_name_type = @constant | @identifier + +#keyset[scope_resolution, index] +scope_resolution_scope( + int scope_resolution: @scope_resolution ref, + int index: int ref, + unique int underscore_primary: @underscore_primary ref +); + +scope_resolution_def( + unique int id: @scope_resolution, + int name: @scope_resolution_name_type ref, + int loc: @location ref +); + +setter_def( + unique int id: @setter, + int child: @identifier ref, + int loc: @location ref +); + +@singleton_class_child_type = @underscore_statement | @else | @empty_statement | @ensure | @rescue + +#keyset[singleton_class, index] +singleton_class_child( + int singleton_class: @singleton_class ref, + int index: int ref, + unique int singleton_class_child_type: @singleton_class_child_type ref +); + +singleton_class_def( + unique int id: @singleton_class, + int value: @underscore_arg ref, + int loc: @location ref +); + +@singleton_method_object_type = @underscore_arg | @underscore_variable + +#keyset[singleton_method, index] +singleton_method_parameters( + int singleton_method: @singleton_method ref, + int index: int ref, + unique int method_parameters: @method_parameters ref +); + +@singleton_method_child_type = @underscore_statement | @else | @empty_statement | @ensure | @rescue + +#keyset[singleton_method, index] +singleton_method_child( + int singleton_method: @singleton_method ref, + int index: int ref, + unique int singleton_method_child_type: @singleton_method_child_type ref +); + +singleton_method_def( + unique int id: @singleton_method, + int name: @underscore_method_name ref, + int object: @singleton_method_object_type ref, + int loc: @location ref +); + +splat_argument_def( + unique int id: @splat_argument, + int child: @underscore_arg ref, + int loc: @location ref +); + +#keyset[splat_parameter, index] +splat_parameter_name( + int splat_parameter: @splat_parameter ref, + int index: int ref, + unique int identifier: @identifier ref +); + +splat_parameter_def( + unique int id: @splat_parameter, + int loc: @location ref +); + +@string_child_type = @escape_sequence | @interpolation + +#keyset[string__, index] +string_child( + int string__: @string__ ref, + int index: int ref, + unique int string_child_type: @string_child_type ref +); + +string_def( + unique int id: @string__, + int loc: @location ref +); + +#keyset[string_array, index] +string_array_child( + int string_array: @string_array ref, + int index: int ref, + unique int bare_string: @bare_string ref +); + +string_array_def( + unique int id: @string_array, + int loc: @location ref +); + +@subshell_child_type = @escape_sequence | @interpolation + +#keyset[subshell, index] +subshell_child( + int subshell: @subshell ref, + int index: int ref, + unique int subshell_child_type: @subshell_child_type ref +); + +subshell_def( + unique int id: @subshell, + int loc: @location ref +); + +@superclass_child_type = @underscore_arg | @break | @call | @method_call | @next | @return | @yield + +superclass_def( + unique int id: @superclass, + int child: @superclass_child_type ref, + int loc: @location ref +); + +@symbol_child_type = @escape_sequence | @interpolation + +#keyset[symbol, index] +symbol_child( + int symbol: @symbol ref, + int index: int ref, + unique int symbol_child_type: @symbol_child_type ref +); + +symbol_def( + unique int id: @symbol, + int loc: @location ref +); + +#keyset[symbol_array, index] +symbol_array_child( + int symbol_array: @symbol_array ref, + int index: int ref, + unique int bare_symbol: @bare_symbol ref +); + +symbol_array_def( + unique int id: @symbol_array, + int loc: @location ref +); + +@then_child_type = @underscore_statement | @empty_statement + +#keyset[then, index] +then_child( + int then: @then ref, + int index: int ref, + unique int then_child_type: @then_child_type ref +); + +then_def( + unique int id: @then, + int loc: @location ref +); + +@unary_child_type = @underscore_arg | @break | @call | @float__ | @integer | @method_call | @next | @parenthesized_statements | @return | @yield + +unary_def( + unique int id: @unary, + int child: @unary_child_type ref, + int loc: @location ref +); + +#keyset[undef, index] +undef_child( + int undef: @undef ref, + int index: int ref, + unique int underscore_method_name: @underscore_method_name ref +); + +undef_def( + unique int id: @undef, + int loc: @location ref +); + +@unless_alternative_type = @else | @elsif + +#keyset[unless, index] +unless_alternative( + int unless: @unless ref, + int index: int ref, + unique int unless_alternative_type: @unless_alternative_type ref +); + +#keyset[unless, index] +unless_consequence( + int unless: @unless ref, + int index: int ref, + unique int then: @then ref +); + +unless_def( + unique int id: @unless, + int condition: @underscore_statement ref, + int loc: @location ref +); + +@unless_modifier_condition_type = @underscore_arg | @break | @call | @method_call | @next | @return | @yield + +unless_modifier_def( + unique int id: @unless_modifier, + int body: @underscore_statement ref, + int condition: @unless_modifier_condition_type ref, + int loc: @location ref +); + +until_def( + unique int id: @until, + int body: @do ref, + int condition: @underscore_statement ref, + int loc: @location ref +); + +@until_modifier_condition_type = @underscore_arg | @break | @call | @method_call | @next | @return | @yield + +until_modifier_def( + unique int id: @until_modifier, + int body: @underscore_statement ref, + int condition: @until_modifier_condition_type ref, + int loc: @location ref +); + +#keyset[when, index] +when_body( + int when: @when ref, + int index: int ref, + unique int then: @then ref +); + +@when_pattern_type = @comma_unnamed | @pattern + +#keyset[when, index] +when_pattern( + int when: @when ref, + int index: int ref, + unique int when_pattern_type: @when_pattern_type ref +); + +when_def( + unique int id: @when, + int loc: @location ref +); + +while_def( + unique int id: @while, + int body: @do ref, + int condition: @underscore_statement ref, + int loc: @location ref +); + +@while_modifier_condition_type = @underscore_arg | @break | @call | @method_call | @next | @return | @yield + +while_modifier_def( + unique int id: @while_modifier, + int body: @underscore_statement ref, + int condition: @while_modifier_condition_type ref, + int loc: @location ref +); + +#keyset[yield, index] +yield_child( + int yield: @yield ref, + int index: int ref, + unique int argument_list: @argument_list ref +); + +yield_def( + unique int id: @yield, + int loc: @location ref +); + +bang_unnamed_def( + unique int id: @bang_unnamed, + string text: string ref, + int loc: @location ref +); + +bangequal_unnamed_def( + unique int id: @bangequal_unnamed, + string text: string ref, + int loc: @location ref +); + +bangtilde_unnamed_def( + unique int id: @bangtilde_unnamed, + string text: string ref, + int loc: @location ref +); + +dquote_unnamed_def( + unique int id: @dquote_unnamed, + string text: string ref, + int loc: @location ref +); + +hashlbrace_unnamed_def( + unique int id: @hashlbrace_unnamed, + string text: string ref, + int loc: @location ref +); + +percent_unnamed_def( + unique int id: @percent_unnamed, + string text: string ref, + int loc: @location ref +); + +percentequal_unnamed_def( + unique int id: @percentequal_unnamed, + string text: string ref, + int loc: @location ref +); + +percentilparen_unnamed_def( + unique int id: @percentilparen_unnamed, + string text: string ref, + int loc: @location ref +); + +percentwlparen_unnamed_def( + unique int id: @percentwlparen_unnamed, + string text: string ref, + int loc: @location ref +); + +ampersand_unnamed_def( + unique int id: @ampersand_unnamed, + string text: string ref, + int loc: @location ref +); + +ampersandampersand_unnamed_def( + unique int id: @ampersandampersand_unnamed, + string text: string ref, + int loc: @location ref +); + +ampersandampersandequal_unnamed_def( + unique int id: @ampersandampersandequal_unnamed, + string text: string ref, + int loc: @location ref +); + +ampersanddot_unnamed_def( + unique int id: @ampersanddot_unnamed, + string text: string ref, + int loc: @location ref +); + +ampersandequal_unnamed_def( + unique int id: @ampersandequal_unnamed, + string text: string ref, + int loc: @location ref +); + +lparen_unnamed_def( + unique int id: @lparen_unnamed, + string text: string ref, + int loc: @location ref +); + +rparen_unnamed_def( + unique int id: @rparen_unnamed, + string text: string ref, + int loc: @location ref +); + +star_unnamed_def( + unique int id: @star_unnamed, + string text: string ref, + int loc: @location ref +); + +starstar_unnamed_def( + unique int id: @starstar_unnamed, + string text: string ref, + int loc: @location ref +); + +starstarequal_unnamed_def( + unique int id: @starstarequal_unnamed, + string text: string ref, + int loc: @location ref +); + +starequal_unnamed_def( + unique int id: @starequal_unnamed, + string text: string ref, + int loc: @location ref +); + +plus_unnamed_def( + unique int id: @plus_unnamed, + string text: string ref, + int loc: @location ref +); + +plusequal_unnamed_def( + unique int id: @plusequal_unnamed, + string text: string ref, + int loc: @location ref +); + +plusat_unnamed_def( + unique int id: @plusat_unnamed, + string text: string ref, + int loc: @location ref +); + +comma_unnamed_def( + unique int id: @comma_unnamed, + string text: string ref, + int loc: @location ref +); + +minus_unnamed_def( + unique int id: @minus_unnamed, + string text: string ref, + int loc: @location ref +); + +minusequal_unnamed_def( + unique int id: @minusequal_unnamed, + string text: string ref, + int loc: @location ref +); + +minusrangle_unnamed_def( + unique int id: @minusrangle_unnamed, + string text: string ref, + int loc: @location ref +); + +minusat_unnamed_def( + unique int id: @minusat_unnamed, + string text: string ref, + int loc: @location ref +); + +dot_unnamed_def( + unique int id: @dot_unnamed, + string text: string ref, + int loc: @location ref +); + +dotdot_unnamed_def( + unique int id: @dotdot_unnamed, + string text: string ref, + int loc: @location ref +); + +dotdotdot_unnamed_def( + unique int id: @dotdotdot_unnamed, + string text: string ref, + int loc: @location ref +); + +slash_unnamed_def( + unique int id: @slash_unnamed, + string text: string ref, + int loc: @location ref +); + +slashequal_unnamed_def( + unique int id: @slashequal_unnamed, + string text: string ref, + int loc: @location ref +); + +colon_unnamed_def( + unique int id: @colon_unnamed, + string text: string ref, + int loc: @location ref +); + +colondquote_unnamed_def( + unique int id: @colondquote_unnamed, + string text: string ref, + int loc: @location ref +); + +coloncolon_unnamed_def( + unique int id: @coloncolon_unnamed, + string text: string ref, + int loc: @location ref +); + +semicolon_unnamed_def( + unique int id: @semicolon_unnamed, + string text: string ref, + int loc: @location ref +); + +langle_unnamed_def( + unique int id: @langle_unnamed, + string text: string ref, + int loc: @location ref +); + +langlelangle_unnamed_def( + unique int id: @langlelangle_unnamed, + string text: string ref, + int loc: @location ref +); + +langlelangleequal_unnamed_def( + unique int id: @langlelangleequal_unnamed, + string text: string ref, + int loc: @location ref +); + +langleequal_unnamed_def( + unique int id: @langleequal_unnamed, + string text: string ref, + int loc: @location ref +); + +langleequalrangle_unnamed_def( + unique int id: @langleequalrangle_unnamed, + string text: string ref, + int loc: @location ref +); + +equal_unnamed_def( + unique int id: @equal_unnamed, + string text: string ref, + int loc: @location ref +); + +equalequal_unnamed_def( + unique int id: @equalequal_unnamed, + string text: string ref, + int loc: @location ref +); + +equalequalequal_unnamed_def( + unique int id: @equalequalequal_unnamed, + string text: string ref, + int loc: @location ref +); + +equalrangle_unnamed_def( + unique int id: @equalrangle_unnamed, + string text: string ref, + int loc: @location ref +); + +equaltilde_unnamed_def( + unique int id: @equaltilde_unnamed, + string text: string ref, + int loc: @location ref +); + +rangle_unnamed_def( + unique int id: @rangle_unnamed, + string text: string ref, + int loc: @location ref +); + +rangleequal_unnamed_def( + unique int id: @rangleequal_unnamed, + string text: string ref, + int loc: @location ref +); + +ranglerangle_unnamed_def( + unique int id: @ranglerangle_unnamed, + string text: string ref, + int loc: @location ref +); + +ranglerangleequal_unnamed_def( + unique int id: @ranglerangleequal_unnamed, + string text: string ref, + int loc: @location ref +); + +question_unnamed_def( + unique int id: @question_unnamed, + string text: string ref, + int loc: @location ref +); + +begin_unnamed_def( + unique int id: @begin_unnamed, + string text: string ref, + int loc: @location ref +); + +end_unnamed_def( + unique int id: @end_unnamed, + string text: string ref, + int loc: @location ref +); + +lbracket_unnamed_def( + unique int id: @lbracket_unnamed, + string text: string ref, + int loc: @location ref +); + +lbracketrbracket_unnamed_def( + unique int id: @lbracketrbracket_unnamed, + string text: string ref, + int loc: @location ref +); + +lbracketrbracketequal_unnamed_def( + unique int id: @lbracketrbracketequal_unnamed, + string text: string ref, + int loc: @location ref +); + +rbracket_unnamed_def( + unique int id: @rbracket_unnamed, + string text: string ref, + int loc: @location ref +); + +caret_unnamed_def( + unique int id: @caret_unnamed, + string text: string ref, + int loc: @location ref +); + +caretequal_unnamed_def( + unique int id: @caretequal_unnamed, + string text: string ref, + int loc: @location ref +); + +underscore__end___unnamed_def( + unique int id: @underscore__end___unnamed, + string text: string ref, + int loc: @location ref +); + +backtick_unnamed_def( + unique int id: @backtick_unnamed, + string text: string ref, + int loc: @location ref +); + +alias_unnamed_def( + unique int id: @alias_unnamed, + string text: string ref, + int loc: @location ref +); + +and_unnamed_def( + unique int id: @and_unnamed, + string text: string ref, + int loc: @location ref +); + +begin_unnamed_def( + unique int id: @begin_unnamed, + string text: string ref, + int loc: @location ref +); + +break_unnamed_def( + unique int id: @break_unnamed, + string text: string ref, + int loc: @location ref +); + +case_unnamed_def( + unique int id: @case_unnamed, + string text: string ref, + int loc: @location ref +); + +character_def( + unique int id: @character, + string text: string ref, + int loc: @location ref +); + +class_unnamed_def( + unique int id: @class_unnamed, + string text: string ref, + int loc: @location ref +); + +class_variable_def( + unique int id: @class_variable, + string text: string ref, + int loc: @location ref +); + +complex_def( + unique int id: @complex, + string text: string ref, + int loc: @location ref +); + +constant_def( + unique int id: @constant, + string text: string ref, + int loc: @location ref +); + +def_unnamed_def( + unique int id: @def_unnamed, + string text: string ref, + int loc: @location ref +); + +definedquestion_unnamed_def( + unique int id: @definedquestion_unnamed, + string text: string ref, + int loc: @location ref +); + +do_unnamed_def( + unique int id: @do_unnamed, + string text: string ref, + int loc: @location ref +); + +else_unnamed_def( + unique int id: @else_unnamed, + string text: string ref, + int loc: @location ref +); + +elsif_unnamed_def( + unique int id: @elsif_unnamed, + string text: string ref, + int loc: @location ref +); + +end_unnamed_def( + unique int id: @end_unnamed, + string text: string ref, + int loc: @location ref +); + +ensure_unnamed_def( + unique int id: @ensure_unnamed, + string text: string ref, + int loc: @location ref +); + +escape_sequence_def( + unique int id: @escape_sequence, + string text: string ref, + int loc: @location ref +); + +false_def( + unique int id: @false, + string text: string ref, + int loc: @location ref +); + +float_def( + unique int id: @float__, + string text: string ref, + int loc: @location ref +); + +for_unnamed_def( + unique int id: @for_unnamed, + string text: string ref, + int loc: @location ref +); + +global_variable_def( + unique int id: @global_variable, + string text: string ref, + int loc: @location ref +); + +heredoc_beginning_def( + unique int id: @heredoc_beginning, + string text: string ref, + int loc: @location ref +); + +heredoc_end_def( + unique int id: @heredoc_end, + string text: string ref, + int loc: @location ref +); + +identifier_def( + unique int id: @identifier, + string text: string ref, + int loc: @location ref +); + +if_unnamed_def( + unique int id: @if_unnamed, + string text: string ref, + int loc: @location ref +); + +in_unnamed_def( + unique int id: @in_unnamed, + string text: string ref, + int loc: @location ref +); + +instance_variable_def( + unique int id: @instance_variable, + string text: string ref, + int loc: @location ref +); + +integer_def( + unique int id: @integer, + string text: string ref, + int loc: @location ref +); + +module_unnamed_def( + unique int id: @module_unnamed, + string text: string ref, + int loc: @location ref +); + +next_unnamed_def( + unique int id: @next_unnamed, + string text: string ref, + int loc: @location ref +); + +nil_def( + unique int id: @nil, + string text: string ref, + int loc: @location ref +); + +not_unnamed_def( + unique int id: @not_unnamed, + string text: string ref, + int loc: @location ref +); + +or_unnamed_def( + unique int id: @or_unnamed, + string text: string ref, + int loc: @location ref +); + +r_unnamed_def( + unique int id: @r_unnamed, + string text: string ref, + int loc: @location ref +); + +redo_unnamed_def( + unique int id: @redo_unnamed, + string text: string ref, + int loc: @location ref +); + +rescue_unnamed_def( + unique int id: @rescue_unnamed, + string text: string ref, + int loc: @location ref +); + +retry_unnamed_def( + unique int id: @retry_unnamed, + string text: string ref, + int loc: @location ref +); + +return_unnamed_def( + unique int id: @return_unnamed, + string text: string ref, + int loc: @location ref +); + +self_def( + unique int id: @self, + string text: string ref, + int loc: @location ref +); + +super_def( + unique int id: @super, + string text: string ref, + int loc: @location ref +); + +then_unnamed_def( + unique int id: @then_unnamed, + string text: string ref, + int loc: @location ref +); + +true_def( + unique int id: @true, + string text: string ref, + int loc: @location ref +); + +undef_unnamed_def( + unique int id: @undef_unnamed, + string text: string ref, + int loc: @location ref +); + +uninterpreted_def( + unique int id: @uninterpreted, + string text: string ref, + int loc: @location ref +); + +unless_unnamed_def( + unique int id: @unless_unnamed, + string text: string ref, + int loc: @location ref +); + +until_unnamed_def( + unique int id: @until_unnamed, + string text: string ref, + int loc: @location ref +); + +when_unnamed_def( + unique int id: @when_unnamed, + string text: string ref, + int loc: @location ref +); + +while_unnamed_def( + unique int id: @while_unnamed, + string text: string ref, + int loc: @location ref +); + +yield_unnamed_def( + unique int id: @yield_unnamed, + string text: string ref, + int loc: @location ref +); + +lbrace_unnamed_def( + unique int id: @lbrace_unnamed, + string text: string ref, + int loc: @location ref +); + +pipe_unnamed_def( + unique int id: @pipe_unnamed, + string text: string ref, + int loc: @location ref +); + +pipeequal_unnamed_def( + unique int id: @pipeequal_unnamed, + string text: string ref, + int loc: @location ref +); + +pipepipe_unnamed_def( + unique int id: @pipepipe_unnamed, + string text: string ref, + int loc: @location ref +); + +pipepipeequal_unnamed_def( + unique int id: @pipepipeequal_unnamed, + string text: string ref, + int loc: @location ref +); + +rbrace_unnamed_def( + unique int id: @rbrace_unnamed, + string text: string ref, + int loc: @location ref +); + +tilde_unnamed_def( + unique int id: @tilde_unnamed, + string text: string ref, + int loc: @location ref +); + +@top = @alias | @argument_list | @array | @assignment | @bare_string | @bare_symbol | @begin | @begin_block | @binary | @block | @block_argument | @block_parameter | @block_parameters | @break | @call | @case__ | @chained_string | @class | @conditional | @destructured_left_assignment | @destructured_parameter | @do | @do_block | @element_reference | @else | @elsif | @empty_statement | @end_block | @ensure | @exception_variable | @exceptions | @for | @hash | @hash_splat_argument | @hash_splat_parameter | @if | @if_modifier | @in | @interpolation | @keyword_parameter | @lambda | @lambda_parameters | @left_assignment_list | @method | @method_call | @method_parameters | @module | @next | @operator | @operator_assignment | @optional_parameter | @pair | @parenthesized_statements | @pattern | @program | @range | @rational | @redo | @regex | @rescue | @rescue_modifier | @rest_assignment | @retry | @return | @right_assignment_list | @scope_resolution | @setter | @singleton_class | @singleton_method | @splat_argument | @splat_parameter | @string__ | @string_array | @subshell | @superclass | @symbol | @symbol_array | @then | @unary | @undef | @unless | @unless_modifier | @until | @until_modifier | @when | @while | @while_modifier | @yield | @bang_unnamed | @bangequal_unnamed | @bangtilde_unnamed | @dquote_unnamed | @hashlbrace_unnamed | @percent_unnamed | @percentequal_unnamed | @percentilparen_unnamed | @percentwlparen_unnamed | @ampersand_unnamed | @ampersandampersand_unnamed | @ampersandampersandequal_unnamed | @ampersanddot_unnamed | @ampersandequal_unnamed | @lparen_unnamed | @rparen_unnamed | @star_unnamed | @starstar_unnamed | @starstarequal_unnamed | @starequal_unnamed | @plus_unnamed | @plusequal_unnamed | @plusat_unnamed | @comma_unnamed | @minus_unnamed | @minusequal_unnamed | @minusrangle_unnamed | @minusat_unnamed | @dot_unnamed | @dotdot_unnamed | @dotdotdot_unnamed | @slash_unnamed | @slashequal_unnamed | @colon_unnamed | @colondquote_unnamed | @coloncolon_unnamed | @semicolon_unnamed | @langle_unnamed | @langlelangle_unnamed | @langlelangleequal_unnamed | @langleequal_unnamed | @langleequalrangle_unnamed | @equal_unnamed | @equalequal_unnamed | @equalequalequal_unnamed | @equalrangle_unnamed | @equaltilde_unnamed | @rangle_unnamed | @rangleequal_unnamed | @ranglerangle_unnamed | @ranglerangleequal_unnamed | @question_unnamed | @begin_unnamed | @end_unnamed | @lbracket_unnamed | @lbracketrbracket_unnamed | @lbracketrbracketequal_unnamed | @rbracket_unnamed | @caret_unnamed | @caretequal_unnamed | @underscore__end___unnamed | @backtick_unnamed | @alias_unnamed | @and_unnamed | @begin_unnamed | @break_unnamed | @case_unnamed | @character | @class_unnamed | @class_variable | @complex | @constant | @def_unnamed | @definedquestion_unnamed | @do_unnamed | @else_unnamed | @elsif_unnamed | @end_unnamed | @ensure_unnamed | @escape_sequence | @false | @float__ | @for_unnamed | @global_variable | @heredoc_beginning | @heredoc_end | @identifier | @if_unnamed | @in_unnamed | @instance_variable | @integer | @module_unnamed | @next_unnamed | @nil | @not_unnamed | @or_unnamed | @r_unnamed | @redo_unnamed | @rescue_unnamed | @retry_unnamed | @return_unnamed | @self | @super | @then_unnamed | @true | @undef_unnamed | @uninterpreted | @unless_unnamed | @until_unnamed | @when_unnamed | @while_unnamed | @yield_unnamed | @lbrace_unnamed | @pipe_unnamed | @pipeequal_unnamed | @pipepipe_unnamed | @pipepipeequal_unnamed | @rbrace_unnamed | @tilde_unnamed + +location( + unique int id: @location, + string file_path: string ref, + int start_line: int ref, + int start_column: int ref, + int end_line: int ref, + int end_column: int ref +); + +sourceLocationPrefix( + string prefix: string ref +); +