From d4366940976a3d150a8b5bf92dc24f0162d4d62c Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 30 Jul 2018 17:02:51 +0300 Subject: Path expressions --- src/grammar.ron | 10 +++++++--- src/parser/grammar/expressions.rs | 27 ++++++++++++++++++++++++++- src/parser/grammar/mod.rs | 1 + src/parser/grammar/paths.rs | 32 +++++++++++++++++++++++++------- src/parser/grammar/type_args.rs | 26 ++++++++++++++++++++++++++ src/syntax_kinds/generated.rs | 16 ++++++++++------ 6 files changed, 95 insertions(+), 17 deletions(-) create mode 100644 src/parser/grammar/type_args.rs (limited to 'src') diff --git a/src/grammar.ron b/src/grammar.ron index d5d2e6162..8232ba1dc 100644 --- a/src/grammar.ron +++ b/src/grammar.ron @@ -120,6 +120,7 @@ Grammar( "PLACEHOLDER_PAT", "TUPLE_EXPR", + "PATH_EXPR", "EXTERN_BLOCK", "ENUM_VARIANT", @@ -133,15 +134,18 @@ Grammar( "LITERAL", "ALIAS", "VISIBILITY", - "TYPE_PARAM_LIST", "WHERE_CLAUSE", - "LIFETIME_PARAM", - "TYPE_PARAM", "ABI", "NAME", "NAME_REF", "VALUE_PARAMETER", "BLOCK", "LET_STMT", + + "TYPE_PARAM", + "LIFETIME_PARAM", + "TYPE_PARAM_LIST", + "TYPE_ARG_LIST", + ] ) diff --git a/src/parser/grammar/expressions.rs b/src/parser/grammar/expressions.rs index 40f41535e..ece698248 100644 --- a/src/parser/grammar/expressions.rs +++ b/src/parser/grammar/expressions.rs @@ -2,7 +2,16 @@ use super::*; // test expr_literals // fn foo() { -// let _ = 92; +// let _ = true; +// let _ = false; +// let _ = 1; +// let _ = 2.0; +// let _ = b'a'; +// let _ = 'b'; +// let _ = "c"; +// let _ = r"d"; +// let _ = b"e"; +// let _ = br"f"; // } pub(super) fn literal(p: &mut Parser) -> bool { match p.current() { @@ -21,6 +30,9 @@ pub(super) fn expr(p: &mut Parser) { if literal(p) { return; } + if paths::is_path_start(p) { + return path_expr(p); + } match p.current() { L_PAREN => tuple_expr(p), @@ -35,3 +47,16 @@ fn tuple_expr(p: &mut Parser) { p.expect(R_PAREN); m.complete(p, TUPLE_EXPR); } + +// test path_expr +// fn foo() { +// let _ = a; +// let _ = a::b; +// let _ = ::a::; +// } +fn path_expr(p: &mut Parser) { + assert!(paths::is_path_start(p)); + let m = p.start(); + paths::expr_path(p); + m.complete(p, PATH_EXPR); +} diff --git a/src/parser/grammar/mod.rs b/src/parser/grammar/mod.rs index e24f1055e..e4823eadb 100644 --- a/src/parser/grammar/mod.rs +++ b/src/parser/grammar/mod.rs @@ -27,6 +27,7 @@ mod items; mod paths; mod patterns; mod type_params; +mod type_args; mod types; use { diff --git a/src/parser/grammar/paths.rs b/src/parser/grammar/paths.rs index d3eb20ea1..69ed84665 100644 --- a/src/parser/grammar/paths.rs +++ b/src/parser/grammar/paths.rs @@ -8,19 +8,26 @@ pub(super) fn is_path_start(p: &Parser) -> bool { } pub(super) fn use_path(p: &mut Parser) { - path(p) + path(p, Mode::Use) } pub(super) fn type_path(p: &mut Parser) { - path(p) + path(p, Mode::Type) } -fn path(p: &mut Parser) { +pub(super) fn expr_path(p: &mut Parser) { + path(p, Mode::Expr) +} + +#[derive(Clone, Copy, Eq, PartialEq)] +enum Mode { Use, Type, Expr } + +fn path(p: &mut Parser, mode: Mode) { if !is_path_start(p) { return; } let path = p.start(); - path_segment(p, true); + path_segment(p, mode, true); let mut qual = path.complete(p, PATH); loop { let use_tree = match p.nth(1) { @@ -30,7 +37,7 @@ fn path(p: &mut Parser) { if p.at(COLONCOLON) && !use_tree { let path = qual.precede(p); p.bump(); - path_segment(p, false); + path_segment(p, mode, false); let path = path.complete(p, PATH); qual = path; } else { @@ -39,13 +46,16 @@ fn path(p: &mut Parser) { } } -fn path_segment(p: &mut Parser, first: bool) { +fn path_segment(p: &mut Parser, mode: Mode, first: bool) { let segment = p.start(); if first { p.eat(COLONCOLON); } match p.current() { - IDENT => name_ref(p), + IDENT => { + name_ref(p); + path_generic_args(p, mode); + }, SELF_KW | SUPER_KW => p.bump(), _ => { p.error("expected identifier"); @@ -53,3 +63,11 @@ fn path_segment(p: &mut Parser, first: bool) { }; segment.complete(p, PATH_SEGMENT); } + +fn path_generic_args(p: &mut Parser, mode: Mode) { + match mode { + Mode::Use => return, + Mode::Type => type_args::list(p, false), + Mode::Expr => type_args::list(p, true), + } +} diff --git a/src/parser/grammar/type_args.rs b/src/parser/grammar/type_args.rs new file mode 100644 index 000000000..20e75b4b0 --- /dev/null +++ b/src/parser/grammar/type_args.rs @@ -0,0 +1,26 @@ +use super::*; + +pub(super) fn list(p: &mut Parser, colon_colon_required: bool) { + let m; + match (colon_colon_required, p.nth(0), p.nth(1)) { + (_, COLONCOLON, L_ANGLE) => { + m = p.start(); + p.bump(); + p.bump(); + } + (false, L_ANGLE, _) => { + m = p.start(); + p.bump(); + } + _ => return + }; + + while !p.at(EOF) && !p.at(R_ANGLE) { + types::type_(p); + if !p.at(R_ANGLE) && !p.expect(COMMA) { + break; + } + } + p.expect(R_ANGLE); + m.complete(p, TYPE_ARG_LIST); +} diff --git a/src/syntax_kinds/generated.rs b/src/syntax_kinds/generated.rs index 029972bb3..bc2a995f6 100644 --- a/src/syntax_kinds/generated.rs +++ b/src/syntax_kinds/generated.rs @@ -115,6 +115,7 @@ pub enum SyntaxKind { BIND_PAT, PLACEHOLDER_PAT, TUPLE_EXPR, + PATH_EXPR, EXTERN_BLOCK, ENUM_VARIANT, NAMED_FIELD, @@ -127,16 +128,17 @@ pub enum SyntaxKind { LITERAL, ALIAS, VISIBILITY, - TYPE_PARAM_LIST, WHERE_CLAUSE, - LIFETIME_PARAM, - TYPE_PARAM, ABI, NAME, NAME_REF, VALUE_PARAMETER, BLOCK, LET_STMT, + TYPE_PARAM, + LIFETIME_PARAM, + TYPE_PARAM_LIST, + TYPE_ARG_LIST, // Technical SyntaxKinds: they appear temporally during parsing, // but never end up in the final tree #[doc(hidden)] @@ -259,6 +261,7 @@ impl SyntaxKind { BIND_PAT => &SyntaxInfo { name: "BIND_PAT" }, PLACEHOLDER_PAT => &SyntaxInfo { name: "PLACEHOLDER_PAT" }, TUPLE_EXPR => &SyntaxInfo { name: "TUPLE_EXPR" }, + PATH_EXPR => &SyntaxInfo { name: "PATH_EXPR" }, EXTERN_BLOCK => &SyntaxInfo { name: "EXTERN_BLOCK" }, ENUM_VARIANT => &SyntaxInfo { name: "ENUM_VARIANT" }, NAMED_FIELD => &SyntaxInfo { name: "NAMED_FIELD" }, @@ -271,16 +274,17 @@ impl SyntaxKind { LITERAL => &SyntaxInfo { name: "LITERAL" }, ALIAS => &SyntaxInfo { name: "ALIAS" }, VISIBILITY => &SyntaxInfo { name: "VISIBILITY" }, - TYPE_PARAM_LIST => &SyntaxInfo { name: "TYPE_PARAM_LIST" }, WHERE_CLAUSE => &SyntaxInfo { name: "WHERE_CLAUSE" }, - LIFETIME_PARAM => &SyntaxInfo { name: "LIFETIME_PARAM" }, - TYPE_PARAM => &SyntaxInfo { name: "TYPE_PARAM" }, ABI => &SyntaxInfo { name: "ABI" }, NAME => &SyntaxInfo { name: "NAME" }, NAME_REF => &SyntaxInfo { name: "NAME_REF" }, VALUE_PARAMETER => &SyntaxInfo { name: "VALUE_PARAMETER" }, BLOCK => &SyntaxInfo { name: "BLOCK" }, LET_STMT => &SyntaxInfo { name: "LET_STMT" }, + TYPE_PARAM => &SyntaxInfo { name: "TYPE_PARAM" }, + LIFETIME_PARAM => &SyntaxInfo { name: "LIFETIME_PARAM" }, + TYPE_PARAM_LIST => &SyntaxInfo { name: "TYPE_PARAM_LIST" }, + TYPE_ARG_LIST => &SyntaxInfo { name: "TYPE_ARG_LIST" }, TOMBSTONE => &SyntaxInfo { name: "TOMBSTONE" }, EOF => &SyntaxInfo { name: "EOF" }, -- cgit v1.2.3