Skip to content
Permalink
Browse files

(LEX): lex `&&` and `&` separately

closes #454
  • Loading branch information...
matklad committed Jun 14, 2016
1 parent fa1c226 commit ba9191ef02855ced88dfeacfd966faad9033c0ea
@@ -346,7 +346,7 @@ self_argument ::= [ '&' LIFETIME? ] MUT? SELF type_ascription?
private restricted_pat ::= &( IDENTIFIER
| '_'
| '&' (IDENTIFIER | '_')
| '&&' (IDENTIFIER | '_')
| '&' '&' (IDENTIFIER | '_')

This comment has been minimized.

@mkaput

mkaput Jun 14, 2016

Member

hmm seems like this case should be removed. Doesn't &&foo mean a reference to reference to foo (&(&foo)) ?

This comment has been minimized.

@bgourlie

bgourlie Jun 14, 2016

Contributor

See rust playground example: https://is.gd/CT3RHj

This comment has been minimized.

@matklad

matklad Jun 14, 2016

Author Member

This is that dreaded pattern in parameter special case again
Valid:

trait T {
    fn f(&&x: &&i32);
}

Invalid:

trait T {
    fn f(&&&x: &&&i32);
}

If Rust 2.0 ever happens, I will do all I can to forbid anonymous function parameters and to get rid of this abomination :)

This comment has been minimized.

@matklad

matklad Jun 14, 2016

Author Member

@bgourlie sorry, I've forgotten to provide context for you. Here is the relevant issue: rust-lang/rfcs#1351

TL;DR: Rust allows omitting name of function parameters for trait methods, and it causes parsing ambiguities between patterns and types.

| MUT IDENTIFIER
) pat

@@ -434,7 +434,6 @@ private pats ::= <<comma_separated_list pat>>
private pat_vec_elts ::= pats? [ '..' [ ',' pats ] ]

pat_reg ::= '&' MUT? pat
| '&&' pat

pat_wild ::= '_'
pat_binding ::= binding_mode? IDENTIFIER !'...' !'::'
@@ -707,7 +706,7 @@ vec_type ::= '[' type [';' any_expr] ']'

ptr_type ::= '*' [ MUT | CONST ] type

ref_type ::= ( '&' | '&&' ) [ LIFETIME? MUT? ] type
ref_type ::= '&' [ LIFETIME? MUT? ] type

bare_fn_type ::= [ UNSAFE? extern_abi? ] FN fn_type_parameters ret_type?

@@ -879,17 +878,17 @@ mul_bin_expr ::= expr ('*' | '/' | '%') expr

// <expr> | <expr> has higher priority than <expr> || <expr>
bool_or_bin_expr ::= expr oror expr
bool_and_bin_expr ::= expr '&&' expr
bool_and_bin_expr ::= expr andand expr
bit_or_bin_expr ::= expr '|' !'|' expr
bit_and_bin_expr ::= expr '&' expr // `&a & &b` is possible
bit_xor_bin_expr ::= expr '^' expr
bit_and_bin_expr ::= expr '&' expr


cast_expr ::= expr AS type

try_expr ::= expr '?'

unary_expr ::= (BOX | '-' | '*' | '!' | ('&' | '&&') MUT?) expr
unary_expr ::= (BOX | '-' | '*' | '!' | '&' MUT?) expr

lambda_expr ::= MOVE? lambda_parameters ret_type? any_expr

@@ -1135,6 +1134,7 @@ private ltlteq ::= <<collapse LTLTEQ LT LT EQ>> | never LTLTEQ { name = "<<=" }
private ltlt ::= <<collapse LTLT LT LT>> | never LTLT { name = "<<" }
private lteq ::= <<collapse LTEQ LT EQ>> | never LTEQ { name = "<=" }
private oror ::= <<collapse OROR OR OR>> | never OROR { name = "||" }
private andand ::= <<collapse ANDAND AND AND>> | never ANDAND { name = "&&" }

private never ::= !()

@@ -157,7 +157,6 @@ STRING_LITERAL = \" ( [^\\\"] | \\[^] )* ( \" {SUFFIX}? | \\ )?
"-" { return MINUS; }
"#" { return SHA; }
"|=" { return OREQ; }
"&&" { return ANDAND; }
"&=" { return ANDEQ; }
"&" { return AND; }
"|" { return OR; }
@@ -362,3 +362,5 @@ mod math {
/* ... */
}
}

fn foo(&& (x, _): && (i32, i32)) {}
@@ -361,3 +361,5 @@ mod math {
/* ... */
}
}

fn foo(&&(x, _): &&(i32, i32)) {}
@@ -14,6 +14,7 @@ fn test() -> u32 {
&x;
&mut x;
&&& x;
&a & &b;

(x + y) * z; /* parenthesized */

@@ -158,13 +158,32 @@ FILE
PsiWhiteSpace('\n ')
RustExprStmtElementImpl(EXPR_STMT)
RustUnaryExprElementImpl(UNARY_EXPR)
PsiElement(&&)('&&')
PsiElement(&)('&')
RustUnaryExprElementImpl(UNARY_EXPR)
PsiElement(&)('&')
RustUnaryExprElementImpl(UNARY_EXPR)
PsiElement(&)('&')
PsiWhiteSpace(' ')
RustPathExprElementImpl(PATH_EXPR)
RustPathElementImpl(PATH)
PsiElement(<IDENTIFIER>)('x')
PsiElement(;)(';')
PsiWhiteSpace('\n ')
RustExprStmtElementImpl(EXPR_STMT)
RustBinaryExprElementImpl(BINARY_EXPR)
RustUnaryExprElementImpl(UNARY_EXPR)
PsiElement(&)('&')
PsiWhiteSpace(' ')
RustPathExprElementImpl(PATH_EXPR)
RustPathElementImpl(PATH)
PsiElement(<IDENTIFIER>)('x')
PsiElement(<IDENTIFIER>)('a')
PsiWhiteSpace(' ')
PsiElement(&)('&')
PsiWhiteSpace(' ')
RustUnaryExprElementImpl(UNARY_EXPR)
PsiElement(&)('&')
RustPathExprElementImpl(PATH_EXPR)
RustPathElementImpl(PATH)
PsiElement(<IDENTIFIER>)('b')
PsiElement(;)(';')
PsiWhiteSpace('\n\n ')
RustExprStmtElementImpl(EXPR_STMT)

2 comments on commit ba9191e

@mkaput

This comment has been minimized.

Copy link
Member

mkaput replied Jun 14, 2016

Also I'd move ANDAND token type declaration in RustTokenElementTypes to the rest of the family.

@matklad

This comment has been minimized.

Copy link
Member Author

matklad replied Jun 14, 2016

ANDAND fixed in c6c14a1

Please sign in to comment.
You can’t perform that action at this time.