QL: switch to shared YAML extractor

This commit is contained in:
Arthur Baars
2023-04-21 16:23:35 +02:00
parent 6d7e95a142
commit d2bc66e393
16 changed files with 200 additions and 374 deletions

BIN
ql/Cargo.lock generated

Binary file not shown.

View File

@@ -10,7 +10,6 @@ edition = "2018"
tree-sitter = ">= 0.20, < 0.21"
tree-sitter-ql = { git = "https://github.com/tree-sitter/tree-sitter-ql.git", rev = "d08db734f8dc52f6bc04db53a966603122bc6985"}
tree-sitter-ql-dbscheme = { git = "https://github.com/erik-krogh/tree-sitter-ql-dbscheme.git", rev = "63e1344353f63931e88bfbc2faa2e78e1421b213"}
tree-sitter-ql-yaml = {git = "https://github.com/erik-krogh/tree-sitter-ql.git", rev = "cf704bf3671e1ae148e173464fb65a4d2bbf5f99"}
tree-sitter-blame = {path = "../buramu/tree-sitter-blame"}
tree-sitter-json = {git = "https://github.com/tausbn/tree-sitter-json.git", rev = "745663ee997f1576fe1e7187e6347e0db36ec7a9"}
clap = { version = "4.2", features = ["derive"] }

View File

@@ -15,7 +15,7 @@ pub fn run(_: Options) -> std::io::Result<()> {
autobuilder::Autobuilder::new("ql", PathBuf::from(database))
.include_extensions(&[".ql", ".qll", ".dbscheme", ".json", ".jsonc", ".jsonl"])
.include_globs(&["**/qlpack.yml", "deprecated.blame"])
.include_globs(&["deprecated.blame"])
.size_limit("10m")
.run()
}

View File

@@ -42,12 +42,6 @@ pub fn run(options: Options) -> std::io::Result<()> {
node_types: tree_sitter_ql_dbscheme::NODE_TYPES,
file_extensions: vec!["dbscheme".into()],
},
simple::LanguageSpec {
prefix: "yaml",
ts_language: tree_sitter_ql_yaml::language(),
node_types: tree_sitter_ql_yaml::NODE_TYPES,
file_extensions: vec!["yml".into()],
},
simple::LanguageSpec {
prefix: "json",
ts_language: tree_sitter_json::language(),

View File

@@ -31,10 +31,6 @@ pub fn run(options: Options) -> std::io::Result<()> {
name: "Dbscheme".to_owned(),
node_types: tree_sitter_ql_dbscheme::NODE_TYPES,
},
Language {
name: "Yaml".to_owned(),
node_types: tree_sitter_ql_yaml::NODE_TYPES,
},
Language {
name: "Blame".to_owned(),
node_types: tree_sitter_blame::NODE_TYPES,

View File

@@ -38,8 +38,6 @@ class AstNode extends TAstNode {
result = node.getLocation()
)
or
result = toGenerateYaml(this).getLocation()
or
result = toDbscheme(this).getLocation()
}
@@ -2573,126 +2571,49 @@ class BindingSet extends Annotation {
* Classes modeling YAML AST nodes.
*/
module YAML {
/** A node in a YAML file */
class YamlNode extends TYamlNode, AstNode {
/** Holds if the predicate is a root node (has no parent) */
predicate isRoot() { not exists(this.getParent()) }
private import codeql.yaml.Yaml as LibYaml
override AstNode getParent() { toGenerateYaml(result) = toGenerateYaml(this).getParent() }
}
private module YamlSig implements LibYaml::InputSig {
import codeql.Locations
/** DEPRECATED: Alias for YamlNode */
deprecated class YAMLNode = YamlNode;
class LocatableBase extends @yaml_locatable {
Location getLocation() { yaml_locations(this, result) }
/** A YAML comment. */
class YamlComment extends TYamlComment, YamlNode {
Yaml::Comment yamlcomment;
YamlComment() { this = TYamlComment(yamlcomment) }
override string getAPrimaryQlClass() { result = "YamlComment" }
}
/** DEPRECATED: Alias for YamlComment */
deprecated class YAMLComment = YamlComment;
/** A YAML entry. */
class YamlEntry extends TYamlEntry, YamlNode {
Yaml::Entry yamle;
YamlEntry() { this = TYamlEntry(yamle) }
/** Gets the key of this YAML entry. */
YamlKey getKey() {
exists(Yaml::Keyvaluepair pair |
pair.getParent() = yamle and
result = TYamlKey(pair.getKey())
)
string toString() { none() }
}
YamlListItem getListItem() { toGenerateYaml(result).getParent() = yamle }
class NodeBase extends LocatableBase, @yaml_node {
NodeBase getChildNode(int i) { yaml(result, _, this, i, _, _) }
/** Gets the value of this YAML entry. */
YamlValue getValue() {
exists(Yaml::Keyvaluepair pair |
pair.getParent() = yamle and
result = TYamlValue(pair.getValue())
)
string getTag() { yaml(this, _, _, _, result, _) }
string getAnchor() { yaml_anchors(this, result) }
override string toString() { yaml(this, _, _, _, _, result) }
}
override string getAPrimaryQlClass() { result = "YamlEntry" }
}
class ScalarNodeBase extends NodeBase, @yaml_scalar_node {
int getStyle() { yaml_scalars(this, result, _) }
/** DEPRECATED: Alias for YamlEntry */
deprecated class YAMLEntry = YamlEntry;
/** A YAML key. */
class YamlKey extends TYamlKey, YamlNode {
Yaml::Key yamlkey;
YamlKey() { this = TYamlKey(yamlkey) }
/**
* Gets the value of this YAML key.
*/
YamlValue getValue() {
exists(Yaml::Keyvaluepair pair |
pair.getKey() = yamlkey and result = TYamlValue(pair.getValue())
)
string getValue() { yaml_scalars(this, _, result) }
}
override string getAPrimaryQlClass() { result = "YamlKey" }
class CollectionNodeBase extends NodeBase, @yaml_collection_node { }
/** Gets the value of this YAML value. */
string getNamePart(int i) {
i = 0 and result = yamlkey.getChild(0).(Yaml::SimpleId).getValue()
or
exists(YamlKey child |
child = TYamlKey(yamlkey.getChild(1)) and
result = child.getNamePart(i - 1)
)
class MappingNodeBase extends CollectionNodeBase, @yaml_mapping_node { }
class SequenceNodeBase extends CollectionNodeBase, @yaml_sequence_node { }
class AliasNodeBase extends NodeBase, @yaml_alias_node {
string getTarget() { yaml_aliases(this, result) }
}
/**
* Gets all the name parts of this YAML key concatenated with `/`.
* Dashes are replaced with `/` (because we don't have that information in the generated AST).
*/
string getQualifiedName() {
result = concat(string part, int i | part = this.getNamePart(i) | part, "/" order by i)
class ParseErrorBase extends LocatableBase, @yaml_error {
string getMessage() { yaml_errors(this, result) }
}
}
/** DEPRECATED: Alias for YamlKey */
deprecated class YAMLKey = YamlKey;
/** A YAML list item. */
class YamlListItem extends TYamlListitem, YamlNode {
Yaml::Listitem yamllistitem;
YamlListItem() { this = TYamlListitem(yamllistitem) }
/**
* Gets the value of this YAML list item.
*/
YamlValue getValue() { result = TYamlValue(yamllistitem.getChild()) }
override string getAPrimaryQlClass() { result = "YamlListItem" }
}
/** DEPRECATED: Alias for YamlListItem */
deprecated class YAMLListItem = YamlListItem;
/** A YAML value. */
class YamlValue extends TYamlValue, YamlNode {
Yaml::Value yamlvalue;
YamlValue() { this = TYamlValue(yamlvalue) }
override string getAPrimaryQlClass() { result = "YamlValue" }
/** Gets the value of this YAML value. */
string getValue() { result = yamlvalue.getValue() }
}
import LibYaml::Make<YamlSig>
// to not expose the entire `File` API on `QlPack`.
private newtype TQLPack = MKQlPack(File file) { file.getBaseName() = "qlpack.yml" }
@@ -2705,15 +2626,16 @@ module YAML {
QLPack() { this = MKQlPack(file) }
private string getProperty(string name) {
exists(YamlEntry entry |
entry.isRoot() and
entry.getKey().getQualifiedName() = name and
result = entry.getValue().getValue().trim() and
entry.getLocation().getFile() = file
private YamlValue get(string name) {
exists(YamlMapping m |
m instanceof YamlDocument and
m.getFile() = file and
result = m.lookup(name)
)
}
private string getProperty(string name) { result = this.get(name).(YamlScalar).getValue() }
/** Gets the name of this qlpack */
string getName() { result = this.getProperty("name") }
@@ -2728,32 +2650,12 @@ module YAML {
/** Gets the file that this `QLPack` represents. */
File getFile() { result = file }
private predicate isADependency(YamlEntry entry) {
exists(YamlEntry deps |
deps.getLocation().getFile() = file and entry.getLocation().getFile() = file
|
deps.isRoot() and
deps.getKey().getQualifiedName() = ["dependencies", "libraryPathDependencies"] and
entry.getLocation().getStartLine() = 1 + deps.getLocation().getStartLine() and
entry.getLocation().getStartColumn() > deps.getLocation().getStartColumn()
)
or
exists(YamlEntry prev | this.isADependency(prev) |
prev.getLocation().getFile() = file and
entry.getLocation().getFile() = file and
entry.getLocation().getStartLine() = 1 + prev.getLocation().getStartLine() and
entry.getLocation().getStartColumn() = prev.getLocation().getStartColumn()
)
}
predicate hasDependency(string name, string version) {
exists(YamlEntry entry | this.isADependency(entry) |
entry.getKey().getQualifiedName().trim() = name and
entry.getValue().getValue() = version
or
name = entry.getListItem().getValue().getValue().trim() and
version = "\"*\""
)
version = this.get("dependencies").(YamlMapping).lookup(name).(YamlScalar).getValue()
or
name =
this.get("libraryPathDependencies").(YamlCollection).getAChild().(YamlScalar).getValue() and
version = "\"*\""
or
name = this.getProperty("libraryPathDependencies") and
version = "\"*\""

View File

@@ -61,11 +61,6 @@ newtype TAstNode =
TPredicateExpr(QL::PredicateExpr pe) or
TAnnotation(QL::Annotation annot) or
TAnnotationArg(QL::AnnotArg arg) or
TYamlComment(Yaml::Comment yc) or
TYamlEntry(Yaml::Entry ye) or
TYamlKey(Yaml::Key yk) or
TYamlListitem(Yaml::Listitem yli) or
TYamlValue(Yaml::Value yv) or
TBuiltinClassless(string ret, string name, string args) { isBuiltinClassless(ret, name, args) } or
TBuiltinMember(string qual, string ret, string name, string args) {
isBuiltinMember(qual, ret, name, args)
@@ -87,15 +82,10 @@ class TCall = TPredicateCall or TMemberCall or TNoneCall or TAnyCall;
class TTypeRef = TImport or TModuleExpr or TType;
class TYamlNode = TYamlComment or TYamlEntry or TYamlKey or TYamlListitem or TYamlValue;
class TSignatureExpr = TPredicateExpr or TType or TModuleExpr;
class TComment = TQLDoc or TBlockComment or TLineComment;
/** DEPRECATED: Alias for TYamlNode */
deprecated class TYAMLNode = TYamlNode;
private QL::AstNode toQLFormula(AST::AstNode n) {
n = TConjunction(result) or
n = TDisjunction(result) or
@@ -125,14 +115,6 @@ private QL::AstNode toQLExpr(AST::AstNode n) {
n = TDontCare(result)
}
Yaml::AstNode toGenerateYaml(AST::AstNode n) {
n = TYamlComment(result) or
n = TYamlEntry(result) or
n = TYamlKey(result) or
n = TYamlListitem(result) or
n = TYamlValue(result)
}
Dbscheme::AstNode toDbscheme(AST::AstNode n) { n = TDBRelation(result) }
/**

View File

@@ -1611,139 +1611,6 @@ module Dbscheme {
}
}
module Yaml {
/** The base class for all AST nodes */
class AstNode extends @yaml_ast_node {
/** Gets a string representation of this element. */
string toString() { result = this.getAPrimaryQlClass() }
/** Gets the location of this element. */
final L::Location getLocation() { yaml_ast_node_info(this, _, _, result) }
/** Gets the parent of this element. */
final AstNode getParent() { yaml_ast_node_info(this, result, _, _) }
/** Gets the index of this node among the children of its parent. */
final int getParentIndex() { yaml_ast_node_info(this, _, result, _) }
/** Gets a field or child node of this node. */
AstNode getAFieldOrChild() { none() }
/** Gets the name of the primary QL class for this element. */
string getAPrimaryQlClass() { result = "???" }
/** Gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs. */
string getPrimaryQlClasses() { result = concat(this.getAPrimaryQlClass(), ",") }
}
/** A token. */
class Token extends @yaml_token, AstNode {
/** Gets the value of this token. */
final string getValue() { yaml_tokeninfo(this, _, result) }
/** Gets a string representation of this element. */
final override string toString() { result = this.getValue() }
/** Gets the name of the primary QL class for this element. */
override string getAPrimaryQlClass() { result = "Token" }
}
/** A reserved word. */
class ReservedWord extends @yaml_reserved_word, Token {
/** Gets the name of the primary QL class for this element. */
final override string getAPrimaryQlClass() { result = "ReservedWord" }
}
/** A class representing `comment` nodes. */
class Comment extends @yaml_comment, AstNode {
/** Gets the name of the primary QL class for this element. */
final override string getAPrimaryQlClass() { result = "Comment" }
/** Gets the child of this node. */
final Value getChild() { yaml_comment_def(this, result) }
/** Gets a field or child node of this node. */
final override AstNode getAFieldOrChild() { yaml_comment_def(this, result) }
}
/** A class representing `entry` nodes. */
class Entry extends @yaml_entry, AstNode {
/** Gets the name of the primary QL class for this element. */
final override string getAPrimaryQlClass() { result = "Entry" }
/** Gets the child of this node. */
final AstNode getChild() { yaml_entry_def(this, result) }
/** Gets a field or child node of this node. */
final override AstNode getAFieldOrChild() { yaml_entry_def(this, result) }
}
/** A class representing `key` nodes. */
class Key extends @yaml_key__, AstNode {
/** Gets the name of the primary QL class for this element. */
final override string getAPrimaryQlClass() { result = "Key" }
/** Gets the `i`th child of this node. */
final AstNode getChild(int i) { yaml_key_child(this, i, result) }
/** Gets a field or child node of this node. */
final override AstNode getAFieldOrChild() { yaml_key_child(this, _, result) }
}
/** A class representing `keyvaluepair` nodes. */
class Keyvaluepair extends @yaml_keyvaluepair, AstNode {
/** Gets the name of the primary QL class for this element. */
final override string getAPrimaryQlClass() { result = "Keyvaluepair" }
/** Gets the node corresponding to the field `key`. */
final Key getKey() { yaml_keyvaluepair_def(this, result, _) }
/** Gets the node corresponding to the field `value`. */
final Value getValue() { yaml_keyvaluepair_def(this, _, result) }
/** Gets a field or child node of this node. */
final override AstNode getAFieldOrChild() {
yaml_keyvaluepair_def(this, result, _) or yaml_keyvaluepair_def(this, _, result)
}
}
/** A class representing `listitem` nodes. */
class Listitem extends @yaml_listitem, AstNode {
/** Gets the name of the primary QL class for this element. */
final override string getAPrimaryQlClass() { result = "Listitem" }
/** Gets the child of this node. */
final Value getChild() { yaml_listitem_def(this, result) }
/** Gets a field or child node of this node. */
final override AstNode getAFieldOrChild() { yaml_listitem_def(this, result) }
}
/** A class representing `simpleId` tokens. */
class SimpleId extends @yaml_token_simple_id, Token {
/** Gets the name of the primary QL class for this element. */
final override string getAPrimaryQlClass() { result = "SimpleId" }
}
/** A class representing `value` tokens. */
class Value extends @yaml_token_value, Token {
/** Gets the name of the primary QL class for this element. */
final override string getAPrimaryQlClass() { result = "Value" }
}
/** A class representing `yaml` nodes. */
class Yaml extends @yaml_yaml, AstNode {
/** Gets the name of the primary QL class for this element. */
final override string getAPrimaryQlClass() { result = "Yaml" }
/** Gets the `i`th child of this node. */
final Entry getChild(int i) { yaml_yaml_child(this, i, result) }
/** Gets a field or child node of this node. */
final override AstNode getAFieldOrChild() { yaml_yaml_child(this, _, result) }
}
}
module Blame {
/** The base class for all AST nodes */
class AstNode extends @blame_ast_node {

View File

@@ -62,6 +62,46 @@ case @diagnostic.severity of
| 30 = @diagnostic_warning
| 40 = @diagnostic_error
;
/*- YAML -*/
#keyset[parent, idx]
yaml (unique int id: @yaml_node,
int kind: int ref,
int parent: @yaml_node_parent ref,
int idx: int ref,
string tag: string ref,
string tostring: string ref);
case @yaml_node.kind of
0 = @yaml_scalar_node
| 1 = @yaml_mapping_node
| 2 = @yaml_sequence_node
| 3 = @yaml_alias_node
;
@yaml_collection_node = @yaml_mapping_node | @yaml_sequence_node;
@yaml_node_parent = @yaml_collection_node | @file;
yaml_anchors (unique int node: @yaml_node ref,
string anchor: string ref);
yaml_aliases (unique int alias: @yaml_alias_node ref,
string target: string ref);
yaml_scalars (unique int scalar: @yaml_scalar_node ref,
int style: int ref,
string value: string ref);
yaml_errors (unique int id: @yaml_error,
string message: string ref);
yaml_locations(unique int locatable: @yaml_locatable ref,
int location: @location_default ref);
@yaml_locatable = @yaml_node | @yaml_error;
/*- QL dbscheme -*/
@ql_add_expr_left_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_unary_expr | @ql_variable
@@ -1129,79 +1169,6 @@ dbscheme_ast_node_info(
int loc: @location_default ref
);
/*- Yaml dbscheme -*/
yaml_comment_def(
unique int id: @yaml_comment,
int child: @yaml_token_value ref
);
@yaml_entry_child_type = @yaml_comment | @yaml_keyvaluepair | @yaml_listitem
yaml_entry_def(
unique int id: @yaml_entry,
int child: @yaml_entry_child_type ref
);
@yaml_key_child_type = @yaml_key__ | @yaml_token_simple_id
#keyset[yaml_key__, index]
yaml_key_child(
int yaml_key__: @yaml_key__ ref,
int index: int ref,
unique int child: @yaml_key_child_type ref
);
yaml_key_def(
unique int id: @yaml_key__
);
yaml_keyvaluepair_def(
unique int id: @yaml_keyvaluepair,
int key__: @yaml_key__ ref,
int value: @yaml_token_value ref
);
yaml_listitem_def(
unique int id: @yaml_listitem,
int child: @yaml_token_value ref
);
#keyset[yaml_yaml, index]
yaml_yaml_child(
int yaml_yaml: @yaml_yaml ref,
int index: int ref,
unique int child: @yaml_entry ref
);
yaml_yaml_def(
unique int id: @yaml_yaml
);
yaml_tokeninfo(
unique int id: @yaml_token,
int kind: int ref,
string value: string ref
);
case @yaml_token.kind of
0 = @yaml_reserved_word
| 1 = @yaml_token_simple_id
| 2 = @yaml_token_value
;
@yaml_ast_node = @yaml_comment | @yaml_entry | @yaml_key__ | @yaml_keyvaluepair | @yaml_listitem | @yaml_token | @yaml_yaml
@yaml_ast_node_parent = @file | @yaml_ast_node
#keyset[parent, parent_index]
yaml_ast_node_info(
unique int node: @yaml_ast_node ref,
int parent: @yaml_ast_node_parent ref,
int parent_index: int ref,
int loc: @location_default ref
);
/*- Blame dbscheme -*/
#keyset[blame_blame_entry, index]
blame_blame_entry_line(

View File

@@ -8,4 +8,5 @@ extractor: ql
dependencies:
codeql/typos: ${workspace}
codeql/util: ${workspace}
codeql/yaml: ${workspace}
warnOnImplicitThis: true

10
ql/tools/pre-finalize.cmd Normal file
View File

@@ -0,0 +1,10 @@
@echo off
type NUL && "%CODEQL_DIST%\codeql" database index-files ^
--include=**/qlpack.yml ^
--size-limit=5m ^
--language yaml ^
-- ^
"%CODEQL_EXTRACTOR_QL_WIP_DATABASE%"
exit /b %ERRORLEVEL%

10
ql/tools/pre-finalize.sh Executable file
View File

@@ -0,0 +1,10 @@
#!/bin/bash
set -eu
"$CODEQL_DIST/codeql" database index-files \
"--include=**/qlpack.yml" \
--size-limit=5m \
--language yaml \
-- \
"$CODEQL_EXTRACTOR_QL_WIP_DATABASE"

View File

@@ -11,4 +11,15 @@ type NUL && "%CODEQL_DIST%\codeql.exe" database index-files ^
--working-dir=. ^
"%CODEQL_EXTRACTOR_QL_WIP_DATABASE%"
IF %ERRORLEVEL% NEQ 0 exit /b %ERRORLEVEL%
type NUL && "%CODEQL_DIST%\codeql.exe" database index-files ^
--prune=**/*.testproj ^
--include-extension=.yml ^
--size-limit=5m ^
--language=yaml ^
--working-dir=. ^
"%CODEQL_EXTRACTOR_QL_WIP_DATABASE%"
exit /b %ERRORLEVEL%

View File

@@ -2,13 +2,20 @@
set -eu
exec "${CODEQL_DIST}/codeql" database index-files \
"${CODEQL_DIST}/codeql" database index-files \
--prune="**/*.testproj" \
--include-extension=.ql \
--include-extension=.qll \
--include-extension=.dbscheme \
--include-extension=.yml \
--size-limit=5m \
--language=ql \
--working-dir=.\
"$CODEQL_EXTRACTOR_QL_WIP_DATABASE"
exec "${CODEQL_DIST}/codeql" database index-files \
--prune="**/*.testproj" \
--include-extension=.yml \
--size-limit=5m \
--language=yaml \
--working-dir=.\
"$CODEQL_EXTRACTOR_QL_WIP_DATABASE"

View File

@@ -62,6 +62,46 @@ case @diagnostic.severity of
| 30 = @diagnostic_warning
| 40 = @diagnostic_error
;
/*- YAML -*/
#keyset[parent, idx]
yaml (unique int id: @yaml_node,
int kind: int ref,
int parent: @yaml_node_parent ref,
int idx: int ref,
string tag: string ref,
string tostring: string ref);
case @yaml_node.kind of
0 = @yaml_scalar_node
| 1 = @yaml_mapping_node
| 2 = @yaml_sequence_node
| 3 = @yaml_alias_node
;
@yaml_collection_node = @yaml_mapping_node | @yaml_sequence_node;
@yaml_node_parent = @yaml_collection_node | @file;
yaml_anchors (unique int node: @yaml_node ref,
string anchor: string ref);
yaml_aliases (unique int alias: @yaml_alias_node ref,
string target: string ref);
yaml_scalars (unique int scalar: @yaml_scalar_node ref,
int style: int ref,
string value: string ref);
yaml_errors (unique int id: @yaml_error,
string message: string ref);
yaml_locations(unique int locatable: @yaml_locatable ref,
int location: @location_default ref);
@yaml_locatable = @yaml_node | @yaml_error;
/*- Ruby dbscheme -*/
@ruby_underscore_arg = @ruby_assignment | @ruby_binary | @ruby_conditional | @ruby_operator_assignment | @ruby_range | @ruby_unary | @ruby_underscore_primary

View File

@@ -59,3 +59,43 @@ case @diagnostic.severity of
| 30 = @diagnostic_warning
| 40 = @diagnostic_error
;
/*- YAML -*/
#keyset[parent, idx]
yaml (unique int id: @yaml_node,
int kind: int ref,
int parent: @yaml_node_parent ref,
int idx: int ref,
string tag: string ref,
string tostring: string ref);
case @yaml_node.kind of
0 = @yaml_scalar_node
| 1 = @yaml_mapping_node
| 2 = @yaml_sequence_node
| 3 = @yaml_alias_node
;
@yaml_collection_node = @yaml_mapping_node | @yaml_sequence_node;
@yaml_node_parent = @yaml_collection_node | @file;
yaml_anchors (unique int node: @yaml_node ref,
string anchor: string ref);
yaml_aliases (unique int alias: @yaml_alias_node ref,
string target: string ref);
yaml_scalars (unique int scalar: @yaml_scalar_node ref,
int style: int ref,
string value: string ref);
yaml_errors (unique int id: @yaml_error,
string message: string ref);
yaml_locations(unique int locatable: @yaml_locatable ref,
int location: @location_default ref);
@yaml_locatable = @yaml_node | @yaml_error;