Add comma list to use tree

This commit is contained in:
Aleksey Kladov 2020-07-30 14:06:04 +02:00
parent be803efb7c
commit 35e7966ebe
3 changed files with 126 additions and 89 deletions

View file

@ -268,6 +268,36 @@ pub struct Rename {
impl ast::NameOwner for Rename {}
impl Rename {
pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) }
pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct UseTree {
pub(crate) syntax: SyntaxNode,
}
impl UseTree {
pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
pub fn star_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![*]) }
pub fn use_tree_list(&self) -> Option<UseTreeList> { support::child(&self.syntax) }
pub fn rename(&self) -> Option<Rename> { support::child(&self.syntax) }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Path {
pub(crate) syntax: SyntaxNode,
}
impl Path {
pub fn qualifier(&self) -> Option<Path> { support::child(&self.syntax) }
pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
pub fn segment(&self) -> Option<PathSegment> { support::child(&self.syntax) }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct UseTreeList {
pub(crate) syntax: SyntaxNode,
}
impl UseTreeList {
pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
pub fn use_trees(&self) -> AstChildren<UseTree> { support::children(&self.syntax) }
pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Abi {
@ -433,15 +463,6 @@ impl PathType {
pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Path {
pub(crate) syntax: SyntaxNode,
}
impl Path {
pub fn qualifier(&self) -> Option<Path> { support::child(&self.syntax) }
pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
pub fn segment(&self) -> Option<PathSegment> { support::child(&self.syntax) }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct PointerType {
pub(crate) syntax: SyntaxNode,
}
@ -1178,26 +1199,6 @@ impl Param {
pub fn dotdotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![...]) }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct UseTree {
pub(crate) syntax: SyntaxNode,
}
impl UseTree {
pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
pub fn star_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![*]) }
pub fn use_tree_list(&self) -> Option<UseTreeList> { support::child(&self.syntax) }
pub fn rename(&self) -> Option<Rename> { support::child(&self.syntax) }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct UseTreeList {
pub(crate) syntax: SyntaxNode,
}
impl UseTreeList {
pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
pub fn use_trees(&self) -> AstChildren<UseTree> { support::children(&self.syntax) }
pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct PathSegment {
pub(crate) syntax: SyntaxNode,
}
@ -1627,6 +1628,39 @@ impl AstNode for Rename {
}
fn syntax(&self) -> &SyntaxNode { &self.syntax }
}
impl AstNode for UseTree {
fn can_cast(kind: SyntaxKind) -> bool { kind == USE_TREE }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
} else {
None
}
}
fn syntax(&self) -> &SyntaxNode { &self.syntax }
}
impl AstNode for Path {
fn can_cast(kind: SyntaxKind) -> bool { kind == PATH }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
} else {
None
}
}
fn syntax(&self) -> &SyntaxNode { &self.syntax }
}
impl AstNode for UseTreeList {
fn can_cast(kind: SyntaxKind) -> bool { kind == USE_TREE_LIST }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
} else {
None
}
}
fn syntax(&self) -> &SyntaxNode { &self.syntax }
}
impl AstNode for Abi {
fn can_cast(kind: SyntaxKind) -> bool { kind == ABI }
fn cast(syntax: SyntaxNode) -> Option<Self> {
@ -1825,17 +1859,6 @@ impl AstNode for PathType {
}
fn syntax(&self) -> &SyntaxNode { &self.syntax }
}
impl AstNode for Path {
fn can_cast(kind: SyntaxKind) -> bool { kind == PATH }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
} else {
None
}
}
fn syntax(&self) -> &SyntaxNode { &self.syntax }
}
impl AstNode for PointerType {
fn can_cast(kind: SyntaxKind) -> bool { kind == POINTER_TYPE }
fn cast(syntax: SyntaxNode) -> Option<Self> {
@ -2672,28 +2695,6 @@ impl AstNode for Param {
}
fn syntax(&self) -> &SyntaxNode { &self.syntax }
}
impl AstNode for UseTree {
fn can_cast(kind: SyntaxKind) -> bool { kind == USE_TREE }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
} else {
None
}
}
fn syntax(&self) -> &SyntaxNode { &self.syntax }
}
impl AstNode for UseTreeList {
fn can_cast(kind: SyntaxKind) -> bool { kind == USE_TREE_LIST }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
} else {
None
}
}
fn syntax(&self) -> &SyntaxNode { &self.syntax }
}
impl AstNode for PathSegment {
fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_SEGMENT }
fn cast(syntax: SyntaxNode) -> Option<Self> {
@ -3560,6 +3561,21 @@ impl std::fmt::Display for Rename {
std::fmt::Display::fmt(self.syntax(), f)
}
}
impl std::fmt::Display for UseTree {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
impl std::fmt::Display for Path {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
impl std::fmt::Display for UseTreeList {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
impl std::fmt::Display for Abi {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
@ -3650,11 +3666,6 @@ impl std::fmt::Display for PathType {
std::fmt::Display::fmt(self.syntax(), f)
}
}
impl std::fmt::Display for Path {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
impl std::fmt::Display for PointerType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
@ -4035,16 +4046,6 @@ impl std::fmt::Display for Param {
std::fmt::Display::fmt(self.syntax(), f)
}
}
impl std::fmt::Display for UseTree {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
impl std::fmt::Display for UseTreeList {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
impl std::fmt::Display for PathSegment {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)

View file

@ -543,6 +543,10 @@ fn lower_enum(grammar: &Grammar, rule: &Rule) -> Option<Vec<String>> {
}
fn lower_rule(acc: &mut Vec<Field>, grammar: &Grammar, rule: &Rule) {
if lower_comma_list(acc, grammar, rule) {
return;
}
match rule {
Rule::Node(node) => {
let field = Field::Node { name: grammar[*node].name.clone(), src: FieldSrc::Shorthand };
@ -595,6 +599,37 @@ fn lower_rule(acc: &mut Vec<Field>, grammar: &Grammar, rule: &Rule) {
}
}
// (T (',' T)* ','?)?
fn lower_comma_list(acc: &mut Vec<Field>, grammar: &Grammar, rule: &Rule) -> bool {
let rule = match rule {
Rule::Opt(it) => it,
_ => return false,
};
let rule = match &**rule {
Rule::Seq(it) => it,
_ => return false,
};
let (node, repeat, trailing_comma) = match rule.as_slice() {
[Rule::Node(node), Rule::Rep(repeat), Rule::Opt(trailing_comma)] => {
(node, repeat, trailing_comma)
}
_ => return false,
};
let repeat = match &**repeat {
Rule::Seq(it) => it,
_ => return false,
};
match repeat.as_slice() {
[comma, Rule::Node(n)] if comma == &**trailing_comma && n == node => (),
_ => return false,
}
let name = grammar[*node].name.clone();
let label = pluralize(&to_lower_snake_case(&name));
let field = Field::Node { name: label.clone(), src: FieldSrc::Many(name) };
acc.push(field);
true
}
fn deduplicate_fields(ast: &mut AstSrc) {
for node in &mut ast.nodes {
let mut i = 0;

View file

@ -29,6 +29,19 @@ ItemList =
ExternCrate =
Attr* Visibility? 'extern' 'crate' (NameRef | 'self') Rename? ';'
Rename =
'as' (Name | '_')
UseItem =
Attr* Visibility? 'use' UseTree ';'
UseTree =
(Path? '::')? ('*' | UseTreeList )
| Path Rename?
UseTreeList =
'{' (UseTree (',' UseTree)* ','?)? '}'
FnDef =
Attr* Visibility? Abi? 'const' 'default' 'async' 'unsafe' 'fn' Name TypeParamList?
ParamList RetType?
@ -395,18 +408,6 @@ Param =
Attr* Pat (':' ascribed_type:TypeRef)
| '...'
UseItem =
Attr* Visibility? 'use' UseTree ';'
UseTree =
Path ('::' ('*' | UseTreeList)) Rename?
UseTreeList =
'{' UseTree* '}'
Rename =
'as' Name
Path =
(qualifier:Path '::')? segment:PathSegment