about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLuca Barbieri <luca@luca-barbieri.com>2020-04-03 21:12:09 +0200
committerAleksey Kladov <aleksey.kladov@gmail.com>2020-04-09 11:50:37 +0200
commit60f4d7bd8c0ecb9f23557464e824140a2be8f41a (patch)
tree00aea343b133272e1df072bd7c839fddf07f36f6
parent85956932872481cf4813c5e7794d981a9edb4623 (diff)
downloadrust-60f4d7bd8c0ecb9f23557464e824140a2be8f41a.tar.gz
rust-60f4d7bd8c0ecb9f23557464e824140a2be8f41a.zip
Provide more complete AST accessors to support usage in rustc
-rw-r--r--crates/ra_assists/src/handlers/add_impl.rs4
-rw-r--r--crates/ra_assists/src/handlers/add_new.rs5
-rw-r--r--crates/ra_assists/src/handlers/introduce_variable.rs4
-rw-r--r--crates/ra_assists/src/handlers/merge_imports.rs4
-rw-r--r--crates/ra_fmt/src/lib.rs6
-rw-r--r--crates/ra_hir_def/src/body/lower.rs10
-rw-r--r--crates/ra_hir_def/src/nameres/raw.rs4
-rw-r--r--crates/ra_hir_def/src/path/lower.rs2
-rw-r--r--crates/ra_hir_def/src/path/lower/lower_use.rs2
-rw-r--r--crates/ra_hir_def/src/visibility.rs4
-rw-r--r--crates/ra_hir_ty/src/tests.rs4
-rw-r--r--crates/ra_parser/src/syntax_kind/generated.rs6
-rw-r--r--crates/ra_syntax/src/ast.rs2
-rw-r--r--crates/ra_syntax/src/ast/edit.rs26
-rw-r--r--crates/ra_syntax/src/ast/expr_extensions.rs4
-rw-r--r--crates/ra_syntax/src/ast/extensions.rs148
-rw-r--r--crates/ra_syntax/src/ast/traits.rs32
-rw-r--r--xtask/src/ast_src.rs383
18 files changed, 436 insertions, 214 deletions
diff --git a/crates/ra_assists/src/handlers/add_impl.rs b/crates/ra_assists/src/handlers/add_impl.rs
index 6622eadb2da..72a201b6d2e 100644
--- a/crates/ra_assists/src/handlers/add_impl.rs
+++ b/crates/ra_assists/src/handlers/add_impl.rs
@@ -1,5 +1,5 @@
 use ra_syntax::{
-    ast::{self, AstNode, NameOwner, TypeParamsOwner},
+    ast::{self, AstNode, AstToken, NameOwner, TypeParamsOwner},
     TextUnit,
 };
 use stdx::{format_to, SepBy};
@@ -42,7 +42,7 @@ pub(crate) fn add_impl(ctx: AssistCtx) -> Option<Assist> {
         if let Some(type_params) = type_params {
             let lifetime_params = type_params
                 .lifetime_params()
-                .filter_map(|it| it.lifetime_token())
+                .filter_map(|it| it.lifetime())
                 .map(|it| it.text().clone());
             let type_params =
                 type_params.type_params().filter_map(|it| it.name()).map(|it| it.text().clone());
diff --git a/crates/ra_assists/src/handlers/add_new.rs b/crates/ra_assists/src/handlers/add_new.rs
index 240b19fa378..c10397249fd 100644
--- a/crates/ra_assists/src/handlers/add_new.rs
+++ b/crates/ra_assists/src/handlers/add_new.rs
@@ -1,7 +1,8 @@
 use hir::Adt;
 use ra_syntax::{
     ast::{
-        self, AstNode, NameOwner, StructKind, TypeAscriptionOwner, TypeParamsOwner, VisibilityOwner,
+        self, AstNode, AstToken, NameOwner, StructKind, TypeAscriptionOwner, TypeParamsOwner,
+        VisibilityOwner,
     },
     TextUnit, T,
 };
@@ -105,7 +106,7 @@ fn generate_impl_text(strukt: &ast::StructDef, code: &str) -> String {
     if let Some(type_params) = type_params {
         let lifetime_params = type_params
             .lifetime_params()
-            .filter_map(|it| it.lifetime_token())
+            .filter_map(|it| it.lifetime())
             .map(|it| it.text().clone());
         let type_params =
             type_params.type_params().filter_map(|it| it.name()).map(|it| it.text().clone());
diff --git a/crates/ra_assists/src/handlers/introduce_variable.rs b/crates/ra_assists/src/handlers/introduce_variable.rs
index 1edbdc14c74..9963f884bb1 100644
--- a/crates/ra_assists/src/handlers/introduce_variable.rs
+++ b/crates/ra_assists/src/handlers/introduce_variable.rs
@@ -1,5 +1,5 @@
 use ra_syntax::{
-    ast::{self, AstNode},
+    ast::{self, AstElement, AstNode},
     SyntaxKind::{
         BLOCK_EXPR, BREAK_EXPR, COMMENT, LAMBDA_EXPR, LOOP_EXPR, MATCH_ARM, PATH_EXPR, RETURN_EXPR,
         WHITESPACE,
@@ -124,7 +124,7 @@ fn anchor_stmt(expr: ast::Expr) -> Option<(SyntaxNode, bool)> {
             }
         }
 
-        if ast::Stmt::cast(node.clone()).is_some() {
+        if ast::Stmt::cast_element(node.clone().into()).is_some() {
             return Some((node, false));
         }
 
diff --git a/crates/ra_assists/src/handlers/merge_imports.rs b/crates/ra_assists/src/handlers/merge_imports.rs
index 5d4b74e567a..f8b3ddb4e18 100644
--- a/crates/ra_assists/src/handlers/merge_imports.rs
+++ b/crates/ra_assists/src/handlers/merge_imports.rs
@@ -3,7 +3,7 @@ use std::iter::successors;
 use ra_syntax::{
     algo::{neighbor, SyntaxRewriter},
     ast::{self, edit::AstNodeEdit, make},
-    AstNode, Direction, InsertPosition, SyntaxElement, T,
+    AstNode, AstToken, Direction, InsertPosition, SyntaxElement, T,
 };
 
 use crate::{Assist, AssistCtx, AssistId};
@@ -82,7 +82,7 @@ fn try_merge_trees(old: &ast::UseTree, new: &ast::UseTree) -> Option<ast::UseTre
             .filter(|it| it.kind() != T!['{'] && it.kind() != T!['}']),
     );
     let use_tree_list = lhs.use_tree_list()?;
-    let pos = InsertPosition::Before(use_tree_list.r_curly()?.into());
+    let pos = InsertPosition::Before(use_tree_list.r_curly()?.syntax().clone().into());
     let use_tree_list = use_tree_list.insert_children(pos, to_insert);
     Some(lhs.with_use_tree_list(use_tree_list))
 }
diff --git a/crates/ra_fmt/src/lib.rs b/crates/ra_fmt/src/lib.rs
index db27f9b8393..0b4ba1bbe65 100644
--- a/crates/ra_fmt/src/lib.rs
+++ b/crates/ra_fmt/src/lib.rs
@@ -60,10 +60,10 @@ pub fn extract_trivial_expression(block: &ast::BlockExpr) -> Option<ast::Expr> {
     } else {
         // Unwrap `{ continue; }`
         let (stmt,) = block.statements().next_tuple()?;
-        if has_anything_else(stmt.syntax()) {
-            return None;
-        }
         if let ast::Stmt::ExprStmt(expr_stmt) = stmt {
+            if has_anything_else(expr_stmt.syntax()) {
+                return None;
+            }
             let expr = expr_stmt.expr()?;
             match expr.syntax().kind() {
                 CONTINUE_EXPR | BREAK_EXPR | RETURN_EXPR => return Some(expr),
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index 8d4b8b0f0fb..8338414faac 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -482,14 +482,17 @@ impl ExprCollector<'_> {
         self.collect_block_items(&block);
         let statements = block
             .statements()
-            .map(|s| match s {
+            .filter_map(|s| match s {
                 ast::Stmt::LetStmt(stmt) => {
                     let pat = self.collect_pat_opt(stmt.pat());
                     let type_ref = stmt.ascribed_type().map(TypeRef::from_ast);
                     let initializer = stmt.initializer().map(|e| self.collect_expr(e));
-                    Statement::Let { pat, type_ref, initializer }
+                    Some(Statement::Let { pat, type_ref, initializer })
                 }
-                ast::Stmt::ExprStmt(stmt) => Statement::Expr(self.collect_expr_opt(stmt.expr())),
+                ast::Stmt::ExprStmt(stmt) => {
+                    Some(Statement::Expr(self.collect_expr_opt(stmt.expr())))
+                }
+                ast::Stmt::ModuleItem(_) => None,
             })
             .collect();
         let tail = block.expr().map(|e| self.collect_expr(e));
@@ -541,6 +544,7 @@ impl ExprCollector<'_> {
                     let ast_id = self.expander.ast_id(&def);
                     (TraitLoc { container, ast_id }.intern(self.db).into(), def.name())
                 }
+                ast::ModuleItem::ExternBlock(_) => continue, // FIXME: collect from extern blocks
                 ast::ModuleItem::ImplDef(_)
                 | ast::ModuleItem::UseItem(_)
                 | ast::ModuleItem::ExternCrateItem(_)
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs
index 8f190e7f917..a9dff3a5d5a 100644
--- a/crates/ra_hir_def/src/nameres/raw.rs
+++ b/crates/ra_hir_def/src/nameres/raw.rs
@@ -266,6 +266,10 @@ impl RawItemsCollector {
                 self.add_macro(current_module, it);
                 return;
             }
+            ast::ModuleItem::ExternBlock(_) => {
+                // FIXME: add extern block
+                return;
+            }
         };
         if let Some(name) = name {
             let name = name.as_name();
diff --git a/crates/ra_hir_def/src/path/lower.rs b/crates/ra_hir_def/src/path/lower.rs
index 4900000fe49..3c13cb2c788 100644
--- a/crates/ra_hir_def/src/path/lower.rs
+++ b/crates/ra_hir_def/src/path/lower.rs
@@ -28,7 +28,7 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
     loop {
         let segment = path.segment()?;
 
-        if segment.has_colon_colon() {
+        if segment.coloncolon().is_some() {
             kind = PathKind::Abs;
         }
 
diff --git a/crates/ra_hir_def/src/path/lower/lower_use.rs b/crates/ra_hir_def/src/path/lower/lower_use.rs
index 278d5196e7b..6ec944228cf 100644
--- a/crates/ra_hir_def/src/path/lower/lower_use.rs
+++ b/crates/ra_hir_def/src/path/lower/lower_use.rs
@@ -34,7 +34,7 @@ pub(crate) fn lower_use_tree(
         let alias = tree.alias().map(|a| {
             a.name().map(|it| it.as_name()).map_or(ImportAlias::Underscore, ImportAlias::Alias)
         });
-        let is_glob = tree.has_star();
+        let is_glob = tree.star().is_some();
         if let Some(ast_path) = tree.path() {
             // Handle self in a path.
             // E.g. `use something::{self, <...>}`
diff --git a/crates/ra_hir_def/src/visibility.rs b/crates/ra_hir_def/src/visibility.rs
index 62513873ef5..1482d3be04d 100644
--- a/crates/ra_hir_def/src/visibility.rs
+++ b/crates/ra_hir_def/src/visibility.rs
@@ -84,6 +84,10 @@ impl RawVisibility {
                 let path = ModPath { kind: PathKind::Super(1), segments: Vec::new() };
                 RawVisibility::Module(path)
             }
+            ast::VisibilityKind::PubSelf => {
+                let path = ModPath { kind: PathKind::Plain, segments: Vec::new() };
+                RawVisibility::Module(path)
+            }
             ast::VisibilityKind::Pub => RawVisibility::Public,
         }
     }
diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs
index 608408d88c2..ac096623682 100644
--- a/crates/ra_hir_ty/src/tests.rs
+++ b/crates/ra_hir_ty/src/tests.rs
@@ -23,7 +23,7 @@ use insta::assert_snapshot;
 use ra_db::{fixture::WithFixture, salsa::Database, FilePosition, SourceDatabase};
 use ra_syntax::{
     algo,
-    ast::{self, AstNode},
+    ast::{self, AstNode, AstToken},
 };
 use stdx::format_to;
 
@@ -101,7 +101,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
             let node = src_ptr.value.to_node(&src_ptr.file_syntax(&db));
 
             let (range, text) = if let Some(self_param) = ast::SelfParam::cast(node.clone()) {
-                (self_param.self_kw_token().text_range(), "self".to_string())
+                (self_param.self_kw().unwrap().syntax().text_range(), "self".to_string())
             } else {
                 (src_ptr.value.range(), node.text().to_string().replace("\n", " "))
             };
diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs
index 4c16cf1cd9a..004f4e56431 100644
--- a/crates/ra_parser/src/syntax_kind/generated.rs
+++ b/crates/ra_parser/src/syntax_kind/generated.rs
@@ -105,6 +105,7 @@ pub enum SyntaxKind {
     DEFAULT_KW,
     EXISTENTIAL_KW,
     UNION_KW,
+    RAW_KW,
     INT_NUMBER,
     FLOAT_NUMBER,
     CHAR,
@@ -258,7 +259,7 @@ impl SyntaxKind {
             | IMPL_KW | IN_KW | LET_KW | LOOP_KW | MACRO_KW | MATCH_KW | MOD_KW | MOVE_KW
             | MUT_KW | PUB_KW | REF_KW | RETURN_KW | SELF_KW | STATIC_KW | STRUCT_KW | SUPER_KW
             | TRAIT_KW | TRUE_KW | TRY_KW | TYPE_KW | UNSAFE_KW | USE_KW | WHERE_KW | WHILE_KW
-            | AUTO_KW | DEFAULT_KW | EXISTENTIAL_KW | UNION_KW => true,
+            | AUTO_KW | DEFAULT_KW | EXISTENTIAL_KW | UNION_KW | RAW_KW => true,
             _ => false,
         }
     }
@@ -651,4 +652,7 @@ macro_rules! T {
     ( union ) => {
         $crate::SyntaxKind::UNION_KW
     };
+    ( raw ) => {
+        $crate::SyntaxKind::RAW_KW
+    };
 }
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs
index ab0f44dd2e0..c81b68d3e29 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -271,7 +271,7 @@ where
     let pred = predicates.next().unwrap();
     let mut bounds = pred.type_bound_list().unwrap().bounds();
 
-    assert_eq!("'a", pred.lifetime_token().unwrap().text());
+    assert_eq!("'a", pred.lifetime().unwrap().text());
 
     assert_bound("'b", bounds.next());
     assert_bound("'c", bounds.next());
diff --git a/crates/ra_syntax/src/ast/edit.rs b/crates/ra_syntax/src/ast/edit.rs
index b69cae234cf..d7931099535 100644
--- a/crates/ra_syntax/src/ast/edit.rs
+++ b/crates/ra_syntax/src/ast/edit.rs
@@ -99,7 +99,7 @@ impl ast::ItemList {
             None => match self.l_curly() {
                 Some(it) => (
                     "    ".to_string() + &leading_indent(self.syntax()).unwrap_or_default(),
-                    InsertPosition::After(it),
+                    InsertPosition::After(it.syntax().clone().into()),
                 ),
                 None => return self.clone(),
             },
@@ -109,10 +109,6 @@ impl ast::ItemList {
             [ws.ws().into(), item.syntax().clone().into()].into();
         self.insert_children(position, to_insert)
     }
-
-    fn l_curly(&self) -> Option<SyntaxElement> {
-        self.syntax().children_with_tokens().find(|it| it.kind() == T!['{'])
-    }
 }
 
 impl ast::RecordFieldList {
@@ -147,7 +143,7 @@ impl ast::RecordFieldList {
         macro_rules! after_l_curly {
             () => {{
                 let anchor = match self.l_curly() {
-                    Some(it) => it,
+                    Some(it) => it.syntax().clone().into(),
                     None => return self.clone(),
                 };
                 InsertPosition::After(anchor)
@@ -189,24 +185,20 @@ impl ast::RecordFieldList {
 
         self.insert_children(position, to_insert)
     }
-
-    fn l_curly(&self) -> Option<SyntaxElement> {
-        self.syntax().children_with_tokens().find(|it| it.kind() == T!['{'])
-    }
 }
 
 impl ast::TypeParam {
     #[must_use]
     pub fn remove_bounds(&self) -> ast::TypeParam {
-        let colon = match self.colon_token() {
+        let colon = match self.colon() {
             Some(it) => it,
             None => return self.clone(),
         };
         let end = match self.type_bound_list() {
             Some(it) => it.syntax().clone().into(),
-            None => colon.clone().into(),
+            None => colon.syntax().clone().into(),
         };
-        self.replace_children(colon.into()..=end, iter::empty())
+        self.replace_children(colon.syntax().clone().into()..=end, iter::empty())
     }
 }
 
@@ -305,8 +297,12 @@ impl ast::UseTree {
             Some(it) => it,
             None => return self.clone(),
         };
-        let use_tree =
-            make::use_tree(suffix.clone(), self.use_tree_list(), self.alias(), self.has_star());
+        let use_tree = make::use_tree(
+            suffix.clone(),
+            self.use_tree_list(),
+            self.alias(),
+            self.star().is_some(),
+        );
         let nested = make::use_tree_list(iter::once(use_tree));
         return make::use_tree(prefix.clone(), Some(nested), None, false);
 
diff --git a/crates/ra_syntax/src/ast/expr_extensions.rs b/crates/ra_syntax/src/ast/expr_extensions.rs
index 8bbd946c071..40c8fca3be3 100644
--- a/crates/ra_syntax/src/ast/expr_extensions.rs
+++ b/crates/ra_syntax/src/ast/expr_extensions.rs
@@ -52,6 +52,10 @@ impl ast::RefExpr {
     pub fn is_mut(&self) -> bool {
         self.syntax().children_with_tokens().any(|n| n.kind() == T![mut])
     }
+
+    pub fn raw_token(&self) -> Option<SyntaxToken> {
+        None // FIXME: implement &raw
+    }
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs
index bf7d137be7d..400eba210af 100644
--- a/crates/ra_syntax/src/ast/extensions.rs
+++ b/crates/ra_syntax/src/ast/extensions.rs
@@ -4,7 +4,10 @@
 use itertools::Itertools;
 
 use crate::{
-    ast::{self, child_opt, children, AstNode, AttrInput, NameOwner, SyntaxNode},
+    ast::{
+        self, child_opt, child_token_opt, children, AstElement, AstNode, AstToken, AttrInput,
+        NameOwner, SyntaxNode,
+    },
     SmolStr, SyntaxElement,
     SyntaxKind::*,
     SyntaxToken, T,
@@ -130,13 +133,6 @@ impl ast::PathSegment {
         };
         Some(res)
     }
-
-    pub fn has_colon_colon(&self) -> bool {
-        match self.syntax.first_child_or_token().map(|s| s.kind()) {
-            Some(T![::]) => true,
-            _ => false,
-        }
-    }
 }
 
 impl ast::Path {
@@ -154,12 +150,6 @@ impl ast::Module {
     }
 }
 
-impl ast::UseTree {
-    pub fn has_star(&self) -> bool {
-        self.syntax().children_with_tokens().any(|it| it.kind() == T![*])
-    }
-}
-
 impl ast::UseTreeList {
     pub fn parent_use_tree(&self) -> ast::UseTree {
         self.syntax()
@@ -167,20 +157,6 @@ impl ast::UseTreeList {
             .and_then(ast::UseTree::cast)
             .expect("UseTreeLists are always nested in UseTrees")
     }
-    pub fn l_curly(&self) -> Option<SyntaxToken> {
-        self.token(T!['{'])
-    }
-
-    pub fn r_curly(&self) -> Option<SyntaxToken> {
-        self.token(T!['}'])
-    }
-
-    fn token(&self, kind: SyntaxKind) -> Option<SyntaxToken> {
-        self.syntax()
-            .children_with_tokens()
-            .filter_map(|it| it.into_token())
-            .find(|it| it.kind() == kind)
-    }
 }
 
 impl ast::ImplDef {
@@ -387,24 +363,9 @@ pub enum SelfParamKind {
 }
 
 impl ast::SelfParam {
-    pub fn self_kw_token(&self) -> SyntaxToken {
-        self.syntax()
-            .children_with_tokens()
-            .filter_map(|it| it.into_token())
-            .find(|it| it.kind() == T![self])
-            .expect("invalid tree: self param must have self")
-    }
-
     pub fn kind(&self) -> SelfParamKind {
-        let borrowed = self.syntax().children_with_tokens().any(|n| n.kind() == T![&]);
-        if borrowed {
-            // check for a `mut` coming after the & -- `mut &self` != `&mut self`
-            if self
-                .syntax()
-                .children_with_tokens()
-                .skip_while(|n| n.kind() != T![&])
-                .any(|n| n.kind() == T![mut])
-            {
+        if self.amp().is_some() {
+            if self.amp_mut_kw().is_some() {
                 SelfParamKind::MutRef
             } else {
                 SelfParamKind::Ref
@@ -413,32 +374,23 @@ impl ast::SelfParam {
             SelfParamKind::Owned
         }
     }
-}
 
-impl ast::LifetimeParam {
-    pub fn lifetime_token(&self) -> Option<SyntaxToken> {
+    /// the "mut" in "mut self", not the one in "&mut self"
+    pub fn mut_kw(&self) -> Option<ast::MutKw> {
         self.syntax()
             .children_with_tokens()
             .filter_map(|it| it.into_token())
-            .find(|it| it.kind() == LIFETIME)
+            .take_while(|it| it.kind() != T![&])
+            .find_map(ast::MutKw::cast)
     }
-}
 
-impl ast::TypeParam {
-    pub fn colon_token(&self) -> Option<SyntaxToken> {
+    /// the "mut" in "&mut self", not the one in "mut self"
+    pub fn amp_mut_kw(&self) -> Option<ast::MutKw> {
         self.syntax()
             .children_with_tokens()
             .filter_map(|it| it.into_token())
-            .find(|it| it.kind() == T![:])
-    }
-}
-
-impl ast::WherePred {
-    pub fn lifetime_token(&self) -> Option<SyntaxToken> {
-        self.syntax()
-            .children_with_tokens()
-            .filter_map(|it| it.into_token())
-            .find(|it| it.kind() == LIFETIME)
+            .skip_while(|it| it.kind() != T![&])
+            .find_map(ast::MutKw::cast)
     }
 }
 
@@ -449,7 +401,7 @@ pub enum TypeBoundKind {
     /// for<'a> ...
     ForType(ast::ForType),
     /// 'a
-    Lifetime(ast::SyntaxToken),
+    Lifetime(ast::Lifetime),
 }
 
 impl ast::TypeBound {
@@ -465,21 +417,28 @@ impl ast::TypeBound {
         }
     }
 
-    fn lifetime(&self) -> Option<SyntaxToken> {
-        self.syntax()
-            .children_with_tokens()
-            .filter_map(|it| it.into_token())
-            .find(|it| it.kind() == LIFETIME)
+    pub fn has_question_mark(&self) -> bool {
+        self.question().is_some()
     }
 
-    pub fn question_mark_token(&self) -> Option<SyntaxToken> {
+    pub fn const_question(&self) -> Option<ast::Question> {
         self.syntax()
             .children_with_tokens()
             .filter_map(|it| it.into_token())
-            .find(|it| it.kind() == T![?])
+            .take_while(|it| it.kind() != T![const])
+            .find_map(ast::Question::cast)
     }
-    pub fn has_question_mark(&self) -> bool {
-        self.question_mark_token().is_some()
+
+    pub fn question(&self) -> Option<ast::Question> {
+        if self.const_kw().is_some() {
+            self.syntax()
+                .children_with_tokens()
+                .filter_map(|it| it.into_token())
+                .skip_while(|it| it.kind() != T![const])
+                .find_map(ast::Question::cast)
+        } else {
+            child_token_opt(self)
+        }
     }
 }
 
@@ -493,6 +452,7 @@ pub enum VisibilityKind {
     In(ast::Path),
     PubCrate,
     PubSuper,
+    PubSelf,
     Pub,
 }
 
@@ -504,6 +464,8 @@ impl ast::Visibility {
             VisibilityKind::PubCrate
         } else if self.is_pub_super() {
             VisibilityKind::PubSuper
+        } else if self.is_pub_self() {
+            VisibilityKind::PubSuper
         } else {
             VisibilityKind::Pub
         }
@@ -516,6 +478,10 @@ impl ast::Visibility {
     fn is_pub_super(&self) -> bool {
         self.syntax().children_with_tokens().any(|it| it.kind() == T![super])
     }
+
+    fn is_pub_self(&self) -> bool {
+        self.syntax().children_with_tokens().any(|it| it.kind() == T![self])
+    }
 }
 
 impl ast::MacroCall {
@@ -528,3 +494,41 @@ impl ast::MacroCall {
         }
     }
 }
+
+impl ast::LifetimeParam {
+    pub fn lifetime_bounds(&self) -> impl Iterator<Item = ast::Lifetime> {
+        self.syntax()
+            .children_with_tokens()
+            .filter_map(|it| it.into_token())
+            .skip_while(|x| x.kind() != T![:])
+            .filter_map(ast::Lifetime::cast)
+    }
+}
+
+impl ast::RangePat {
+    pub fn start(&self) -> Option<ast::Pat> {
+        self.syntax()
+            .children_with_tokens()
+            .take_while(|it| !ast::RangeSeparator::can_cast_element(it.kind()))
+            .filter_map(|it| it.into_node())
+            .find_map(ast::Pat::cast)
+    }
+
+    pub fn end(&self) -> Option<ast::Pat> {
+        self.syntax()
+            .children_with_tokens()
+            .skip_while(|it| !ast::RangeSeparator::can_cast_element(it.kind()))
+            .filter_map(|it| it.into_node())
+            .find_map(ast::Pat::cast)
+    }
+}
+
+impl ast::TokenTree {
+    pub fn left_delimiter(&self) -> Option<ast::LeftDelimiter> {
+        self.syntax().first_child_or_token().and_then(ast::LeftDelimiter::cast_element)
+    }
+
+    pub fn right_delimiter(&self) -> Option<ast::RightDelimiter> {
+        self.syntax().last_child_or_token().and_then(ast::RightDelimiter::cast_element)
+    }
+}
diff --git a/crates/ra_syntax/src/ast/traits.rs b/crates/ra_syntax/src/ast/traits.rs
index 576378306f4..e6f3a4ebb7c 100644
--- a/crates/ra_syntax/src/ast/traits.rs
+++ b/crates/ra_syntax/src/ast/traits.rs
@@ -4,9 +4,9 @@
 
 use itertools::Itertools;
 
-use crate::{
-    ast::{self, child_opt, children, AstChildren, AstNode, AstToken},
-    syntax_node::SyntaxElementChildren,
+use crate::ast::{
+    self, child_elements, child_opt, child_token_opt, child_tokens, children, AstChildElements,
+    AstChildTokens, AstChildren, AstNode, AstToken,
 };
 
 pub trait TypeAscriptionOwner: AstNode {
@@ -31,6 +31,10 @@ pub trait LoopBodyOwner: AstNode {
     fn loop_body(&self) -> Option<ast::BlockExpr> {
         child_opt(self)
     }
+
+    fn label(&self) -> Option<ast::Label> {
+        child_opt(self)
+    }
 }
 
 pub trait ArgListOwner: AstNode {
@@ -65,6 +69,10 @@ pub trait TypeBoundsOwner: AstNode {
     fn type_bound_list(&self) -> Option<ast::TypeBoundList> {
         child_opt(self)
     }
+
+    fn colon(&self) -> Option<ast::Colon> {
+        child_token_opt(self)
+    }
 }
 
 pub trait AttrsOwner: AstNode {
@@ -74,11 +82,14 @@ pub trait AttrsOwner: AstNode {
     fn has_atom_attr(&self, atom: &str) -> bool {
         self.attrs().filter_map(|x| x.as_simple_atom()).any(|x| x == atom)
     }
+    fn attr_or_comments(&self) -> AstChildElements<ast::AttrOrComment> {
+        child_elements(self)
+    }
 }
 
 pub trait DocCommentsOwner: AstNode {
-    fn doc_comments(&self) -> CommentIter {
-        CommentIter { iter: self.syntax().children_with_tokens() }
+    fn doc_comments(&self) -> AstChildTokens<ast::Comment> {
+        child_tokens(self)
     }
 
     /// Returns the textual content of a doc comment block as a single string.
@@ -123,14 +134,3 @@ pub trait DocCommentsOwner: AstNode {
         }
     }
 }
-
-pub struct CommentIter {
-    iter: SyntaxElementChildren,
-}
-
-impl Iterator for CommentIter {
-    type Item = ast::Comment;
-    fn next(&mut self) -> Option<ast::Comment> {
-        self.iter.by_ref().find_map(|el| el.into_token().and_then(ast::Comment::cast))
-    }
-}
diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs
index d9f51ec3994..3200acc8676 100644
--- a/xtask/src/ast_src.rs
+++ b/xtask/src/ast_src.rs
@@ -70,7 +70,7 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc {
         "match", "mod", "move", "mut", "pub", "ref", "return", "self", "static", "struct", "super",
         "trait", "true", "try", "type", "unsafe", "use", "where", "while",
     ],
-    contextual_keywords: &["auto", "default", "existential", "union"],
+    contextual_keywords: &["auto", "default", "existential", "union", "raw"],
     literals: &[
         "INT_NUMBER",
         "FLOAT_NUMBER",
@@ -297,235 +297,311 @@ macro_rules! ast_enums {
 
 pub(crate) const AST_SRC: AstSrc = AstSrc {
     nodes: &ast_nodes! {
-        struct SourceFile: ModuleItemOwner, FnDefOwner {
+        struct SourceFile: ModuleItemOwner, FnDefOwner, AttrsOwner {
             modules: [Module],
         }
 
         struct FnDef: VisibilityOwner, NameOwner, TypeParamsOwner, DocCommentsOwner, AttrsOwner {
+            Abi,
+            ConstKw,
+            DefaultKw,
+            AsyncKw,
+            UnsafeKw,
+            FnKw,
             ParamList,
             RetType,
             body: BlockExpr,
+            Semi
         }
 
-        struct RetType { TypeRef }
+        struct RetType { ThinArrow, TypeRef }
 
         struct StructDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner {
+            StructKw,
+            FieldDefList,
+            Semi
         }
 
         struct UnionDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner {
+            UnionKw,
             RecordFieldDefList,
         }
 
-        struct RecordFieldDefList { fields: [RecordFieldDef] }
+        struct RecordFieldDefList { LCurly, fields: [RecordFieldDef], RCurly }
         struct RecordFieldDef: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner { }
 
-        struct TupleFieldDefList { fields: [TupleFieldDef] }
+        struct TupleFieldDefList { LParen, fields: [TupleFieldDef], RParen }
         struct TupleFieldDef: VisibilityOwner, AttrsOwner {
             TypeRef,
         }
 
         struct EnumDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner {
+            EnumKw,
             variant_list: EnumVariantList,
         }
         struct EnumVariantList {
+            LCurly,
             variants: [EnumVariant],
+            RCurly
         }
-        struct EnumVariant: NameOwner, DocCommentsOwner, AttrsOwner {
+        struct EnumVariant: VisibilityOwner, NameOwner, DocCommentsOwner, AttrsOwner {
+            FieldDefList,
+            Eq,
             Expr
         }
 
         struct TraitDef: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner, TypeParamsOwner, TypeBoundsOwner {
+            UnsafeKw,
+            AutoKw,
+            TraitKw,
             ItemList,
         }
 
         struct Module: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner {
+            ModKw,
             ItemList,
+            Semi
         }
 
         struct ItemList: FnDefOwner, ModuleItemOwner {
+            LCurly,
             impl_items: [ImplItem],
+            RCurly
         }
 
         struct ConstDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner {
+            DefaultKw,
+            ConstKw,
+            Eq,
             body: Expr,
+            Semi
         }
 
         struct StaticDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner {
+            StaticKw,
+            MutKw,
+            Eq,
             body: Expr,
+            Semi
         }
 
         struct TypeAliasDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeBoundsOwner {
+            DefaultKw,
+            TypeKw,
+            Eq,
             TypeRef,
+            Semi
         }
 
         struct ImplDef: TypeParamsOwner, AttrsOwner {
+            DefaultKw,
+            ConstKw,
+            UnsafeKw,
+            ImplKw,
+            Excl,
+            ForKw,
             ItemList,
         }
 
-        struct ParenType { TypeRef }
-        struct TupleType { fields: [TypeRef] }
-        struct NeverType { }
+        struct ParenType { LParen, TypeRef, RParen }
+        struct TupleType { LParen, fields: [TypeRef], RParen }
+        struct NeverType { Excl }
         struct PathType { Path }
-        struct PointerType { TypeRef }
-        struct ArrayType { TypeRef, Expr }
-        struct SliceType { TypeRef }
-        struct ReferenceType { TypeRef }
-        struct PlaceholderType {  }
-        struct FnPointerType { ParamList, RetType }
-        struct ForType { TypeRef }
-        struct ImplTraitType: TypeBoundsOwner {}
-        struct DynTraitType: TypeBoundsOwner {}
-
-        struct TupleExpr { exprs: [Expr] }
-        struct ArrayExpr { exprs: [Expr] }
-        struct ParenExpr { Expr }
+        struct PointerType { Star, ConstKw, TypeRef }
+        struct ArrayType { LBrack, TypeRef, Semi, Expr, RBrack }
+        struct SliceType { LBrack, TypeRef, RBrack }
+        struct ReferenceType { Amp, Lifetime, MutKw, TypeRef }
+        struct PlaceholderType { Underscore }
+        struct FnPointerType { Abi, UnsafeKw, FnKw, ParamList, RetType }
+        struct ForType { ForKw, TypeParamList, TypeRef }
+        struct ImplTraitType: TypeBoundsOwner { ImplKw }
+        struct DynTraitType: TypeBoundsOwner { DynKw }
+
+        struct TupleExpr: AttrsOwner { LParen, exprs: [Expr], RParen }
+        struct ArrayExpr: AttrsOwner { LBrack, exprs: [Expr], Semi, RBrack }
+        struct ParenExpr: AttrsOwner { LParen, Expr, RParen }
         struct PathExpr  { Path }
-        struct LambdaExpr {
+        struct LambdaExpr: AttrsOwner {
+            StaticKw,
+            AsyncKw,
+            MoveKw,
             ParamList,
             RetType,
             body: Expr,
         }
-        struct IfExpr { Condition }
-        struct LoopExpr: LoopBodyOwner { }
-        struct TryBlockExpr { body: BlockExpr }
-        struct ForExpr: LoopBodyOwner {
+        struct IfExpr: AttrsOwner { IfKw, Condition }
+        struct LoopExpr: AttrsOwner, LoopBodyOwner { LoopKw }
+        struct TryBlockExpr: AttrsOwner { TryKw, body: BlockExpr }
+        struct ForExpr: AttrsOwner, LoopBodyOwner {
+            ForKw,
             Pat,
+            InKw,
             iterable: Expr,
         }
-        struct WhileExpr: LoopBodyOwner { Condition }
-        struct ContinueExpr {}
-        struct BreakExpr { Expr }
-        struct Label {}
-        struct BlockExpr { Block  }
-        struct ReturnExpr { Expr }
+        struct WhileExpr: AttrsOwner, LoopBodyOwner { WhileKw, Condition }
+        struct ContinueExpr: AttrsOwner { ContinueKw, Lifetime }
+        struct BreakExpr: AttrsOwner { BreakKw, Lifetime, Expr }
+        struct Label { Lifetime }
+        struct BlockExpr: AttrsOwner { Label, UnsafeKw, Block  }
+        struct ReturnExpr: AttrsOwner { Expr }
         struct CallExpr: ArgListOwner { Expr }
-        struct MethodCallExpr: ArgListOwner {
-            Expr, NameRef, TypeArgList,
-        }
-        struct IndexExpr {}
-        struct FieldExpr { Expr, NameRef }
-        struct AwaitExpr { Expr }
-        struct TryExpr { Expr }
-        struct CastExpr { Expr, TypeRef }
-        struct RefExpr { Expr }
-        struct PrefixExpr { Expr }
-        struct BoxExpr { Expr }
-        struct RangeExpr {}
-        struct BinExpr {}
-        struct Literal {}
-
-        struct MatchExpr { Expr, MatchArmList }
-        struct MatchArmList: AttrsOwner { arms: [MatchArm] }
+        struct MethodCallExpr: AttrsOwner, ArgListOwner {
+            Expr, Dot, NameRef, TypeArgList,
+        }
+        struct IndexExpr: AttrsOwner { LBrack, RBrack }
+        struct FieldExpr: AttrsOwner { Expr, Dot, NameRef }
+        struct AwaitExpr: AttrsOwner { Expr, Dot, AwaitKw }
+        struct TryExpr: AttrsOwner { TryKw, Expr }
+        struct CastExpr: AttrsOwner { Expr, AsKw, TypeRef }
+        struct RefExpr: AttrsOwner { Amp, RawKw, MutKw, Expr }
+        struct PrefixExpr: AttrsOwner { PrefixOp, Expr }
+        struct BoxExpr: AttrsOwner { BoxKw, Expr }
+        struct RangeExpr: AttrsOwner { RangeOp }
+        struct BinExpr: AttrsOwner { BinOp }
+        struct Literal { LiteralToken }
+
+        struct MatchExpr: AttrsOwner { MatchKw, Expr, MatchArmList }
+        struct MatchArmList: AttrsOwner { LCurly, arms: [MatchArm], RCurly }
         struct MatchArm: AttrsOwner {
             pat: Pat,
             guard: MatchGuard,
+            FatArrow,
             Expr,
         }
-        struct MatchGuard { Expr }
+        struct MatchGuard { IfKw, Expr }
 
-        struct RecordLit { Path, RecordFieldList }
+        struct RecordLit { Path, RecordFieldList}
         struct RecordFieldList {
+            LCurly,
             fields: [RecordField],
+            Dotdot,
             spread: Expr,
+            RCurly
         }
-        struct RecordField { NameRef, Expr }
+        struct RecordField: AttrsOwner { NameRef, Colon, Expr }
 
         struct OrPat { pats: [Pat] }
-        struct ParenPat { Pat }
-        struct RefPat { Pat }
-        struct BoxPat { Pat }
-        struct BindPat: NameOwner { Pat }
-        struct PlaceholderPat { }
-        struct DotDotPat { }
+        struct ParenPat { LParen, Pat, RParen }
+        struct RefPat { Amp, MutKw, Pat }
+        struct BoxPat { BoxKw, Pat }
+        struct BindPat: AttrsOwner, NameOwner { RefKw, MutKw, Pat }
+        struct PlaceholderPat { Underscore }
+        struct DotDotPat { Dotdot }
         struct PathPat { Path }
-        struct SlicePat { args: [Pat] }
-        struct RangePat {}
+        struct SlicePat { LBrack, args: [Pat], RBrack }
+        struct RangePat { RangeSeparator }
         struct LiteralPat { Literal }
         struct MacroPat { MacroCall }
 
         struct RecordPat { RecordFieldPatList, Path }
         struct RecordFieldPatList {
+            LCurly,
+            pats: [RecordInnerPat],
             record_field_pats: [RecordFieldPat],
             bind_pats: [BindPat],
+            Dotdot,
+            RCurly
         }
-        struct RecordFieldPat: NameOwner { Pat }
+        struct RecordFieldPat: AttrsOwner, NameOwner { Colon, Pat }
 
-        struct TupleStructPat { Path, args: [Pat] }
-        struct TuplePat { args: [Pat] }
+        struct TupleStructPat { Path, LParen, args: [Pat], RParen }
+        struct TuplePat { LParen, args: [Pat], RParen }
 
-        struct Visibility {}
-        struct Name {}
-        struct NameRef {}
+        struct Visibility { PubKw, SuperKw, SelfKw, CrateKw }
+        struct Name { Ident }
+        struct NameRef { NameRefToken }
 
         struct MacroCall: NameOwner, AttrsOwner,DocCommentsOwner {
-            TokenTree, Path
+            Path, Excl, TokenTree, Semi
         }
-        struct Attr { Path, input: AttrInput }
+        struct Attr { Pound, Excl, LBrack, Path, Eq, input: AttrInput, RBrack }
         struct TokenTree {}
         struct TypeParamList {
+            LAngle,
+            generic_params: [GenericParam],
             type_params: [TypeParam],
             lifetime_params: [LifetimeParam],
+            const_params: [ConstParam],
+            RAngle
         }
         struct TypeParam: NameOwner, AttrsOwner, TypeBoundsOwner {
+            Eq,
             default_type: TypeRef,
         }
         struct ConstParam: NameOwner, AttrsOwner, TypeAscriptionOwner {
+            Eq,
             default_val: Expr,
         }
-        struct LifetimeParam: AttrsOwner { }
-        struct TypeBound { TypeRef}
+        struct LifetimeParam: AttrsOwner { Lifetime}
+        struct TypeBound { Lifetime, /* Question,  */ ConstKw, /* Question,  */ TypeRef}
         struct TypeBoundList { bounds: [TypeBound] }
-        struct WherePred: TypeBoundsOwner { TypeRef }
-        struct WhereClause { predicates: [WherePred] }
-        struct ExprStmt { Expr }
-        struct LetStmt: TypeAscriptionOwner {
+        struct WherePred: TypeBoundsOwner { Lifetime, TypeRef }
+        struct WhereClause { WhereKw, predicates: [WherePred] }
+        struct Abi { String }
+        struct ExprStmt: AttrsOwner { Expr, Semi }
+        struct LetStmt: AttrsOwner, TypeAscriptionOwner {
+            LetKw,
             Pat,
+            Eq,
             initializer: Expr,
         }
-        struct Condition { Pat, Expr }
+        struct Condition { LetKw, Pat, Eq, Expr }
         struct Block: AttrsOwner, ModuleItemOwner {
+            LCurly,
             statements: [Stmt],
+            statements_or_semi: [StmtOrSemi],
             Expr,
+            RCurly,
         }
         struct ParamList {
+            LParen,
             SelfParam,
             params: [Param],
+            RParen
         }
-        struct SelfParam: TypeAscriptionOwner, AttrsOwner { }
+        struct SelfParam: TypeAscriptionOwner, AttrsOwner { Amp, Lifetime, SelfKw }
         struct Param: TypeAscriptionOwner, AttrsOwner {
             Pat,
+            Dotdotdot
         }
         struct UseItem: AttrsOwner, VisibilityOwner {
+            UseKw,
             UseTree,
         }
         struct UseTree {
-            Path, UseTreeList, Alias
+            Path, Star, UseTreeList, Alias
         }
-        struct Alias: NameOwner { }
-        struct UseTreeList { use_trees: [UseTree] }
+        struct Alias: NameOwner { AsKw }
+        struct UseTreeList { LCurly, use_trees: [UseTree], RCurly }
         struct ExternCrateItem: AttrsOwner, VisibilityOwner {
-            NameRef, Alias,
+            ExternKw, CrateKw, NameRef, Alias,
         }
         struct ArgList {
+            LParen,
             args: [Expr],
+            RParen
         }
         struct Path {
             segment: PathSegment,
             qualifier: Path,
         }
         struct PathSegment {
-            NameRef, TypeArgList, ParamList, RetType, PathType,
+            Coloncolon, LAngle, NameRef, TypeArgList, ParamList, RetType, PathType, RAngle
         }
         struct TypeArgList {
+            Coloncolon,
+            LAngle,
+            generic_args: [GenericArg],
             type_args: [TypeArg],
             lifetime_args: [LifetimeArg],
             assoc_type_args: [AssocTypeArg],
-            const_arg: [ConstArg],
+            const_args: [ConstArg],
+            RAngle
         }
         struct TypeArg { TypeRef }
-        struct AssocTypeArg { NameRef, TypeRef }
-        struct LifetimeArg {}
-        struct ConstArg { Literal, BlockExpr }
+        struct AssocTypeArg : TypeBoundsOwner { NameRef, Eq, TypeRef }
+        struct LifetimeArg { Lifetime }
+        struct ConstArg { Literal, Eq, BlockExpr }
 
         struct MacroItems: ModuleItemOwner, FnDefOwner { }
 
@@ -533,12 +609,44 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
             statements: [Stmt],
             Expr,
         }
+
+        struct ExternItemList: FnDefOwner, ModuleItemOwner {
+            LCurly,
+            extern_items: [ExternItem],
+            RCurly
+        }
+
+        struct ExternBlock {
+            Abi,
+            ExternItemList
+        }
+
+        struct MetaItem {
+            Path, Eq, AttrInput, nested_meta_items: [MetaItem]
+        }
+
+        struct MacroDef {
+            Name, TokenTree
+        }
     },
     enums: &ast_enums! {
         enum NominalDef: NameOwner, TypeParamsOwner, AttrsOwner {
             StructDef, EnumDef, UnionDef,
         }
 
+        enum GenericParam {
+            LifetimeParam,
+            TypeParam,
+            ConstParam
+        }
+
+        enum GenericArg {
+            LifetimeArg,
+            TypeArg,
+            ConstArg,
+            AssocTypeArg
+        }
+
         enum TypeRef {
             ParenType,
             TupleType,
@@ -555,7 +663,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
             DynTraitType,
         }
 
-        enum ModuleItem: AttrsOwner, VisibilityOwner {
+        enum ModuleItem: NameOwner, AttrsOwner, VisibilityOwner {
             StructDef,
             UnionDef,
             EnumDef,
@@ -569,13 +677,20 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
             StaticDef,
             Module,
             MacroCall,
+            ExternBlock
         }
 
-        enum ImplItem: AttrsOwner {
-            FnDef, TypeAliasDef, ConstDef,
+        /* impl blocks can also contain MacroCall */
+        enum ImplItem: NameOwner, AttrsOwner {
+            FnDef, TypeAliasDef, ConstDef
         }
 
-        enum Expr {
+        /* extern blocks can also contain MacroCall */
+        enum ExternItem: NameOwner, AttrsOwner, VisibilityOwner {
+            FnDef, StaticDef
+        }
+
+        enum Expr: AttrsOwner {
             TupleExpr,
             ArrayExpr,
             ParenExpr,
@@ -627,7 +742,93 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
             MacroPat,
         }
 
+        enum RecordInnerPat {
+            RecordFieldPat,
+            BindPat
+        }
+
         enum AttrInput { Literal, TokenTree }
-        enum Stmt { ExprStmt, LetStmt }
+        enum Stmt {
+            ModuleItem,
+            LetStmt,
+            ExprStmt,
+            // macro calls are parsed as expression statements */
+        }
+        enum StmtOrSemi {Stmt, Semi}
+
+        enum LeftDelimiter { LParen, LBrack, LCurly }
+        enum RightDelimiter { RParen, RBrack, RCurly }
+        enum RangeSeparator { Dotdot, Dotdotdot, Dotdoteq}
+
+        enum BinOp {
+            Pipepipe,
+            Ampamp,
+            Eqeq,
+            Neq,
+            Lteq,
+            Gteq,
+            LAngle,
+            RAngle,
+            Plus,
+            Star,
+            Minus,
+            Slash,
+            Percent,
+            Shl,
+            Shr,
+            Caret,
+            Pipe,
+            Amp,
+            Eq,
+            Pluseq,
+            Slasheq,
+            Stareq,
+            Percenteq,
+            Shreq,
+            Shleq,
+            Minuseq,
+            Pipeeq,
+            Ampeq,
+            Careteq,
+        }
+
+        enum PrefixOp {
+            Minus,
+            Excl,
+            Star
+        }
+
+        enum RangeOp {
+            Dotdot,
+            Dotdoteq
+        }
+
+        enum LiteralToken {
+            IntNumber,
+            FloatNumber,
+            String,
+            RawString,
+            TrueKw,
+            FalseKw,
+            ByteString,
+            RawByteString,
+            Char,
+            Byte
+        }
+
+        enum NameRefToken {
+            Ident,
+            IntNumber
+        }
+
+        enum FieldDefList {
+            RecordFieldDefList,
+            TupleFieldDefList,
+        }
+
+        enum AttrOrComment {
+            Attr,
+            Comment
+        }
     },
 };