Skip to content

Commit

Permalink
Auto merge of #29072 - nagisa:place-arrow, r=pnkfelix
Browse files Browse the repository at this point in the history
This commit generalises parsing of associative operators from left-associative
only (with some ugly hacks to support right-associative assignment) to properly
left/right-associative operators.

Parsing is still is not general enough to handle non-associative,
non-highest-precedence prefix or non-highest-precedence
postfix operators (e.g. `..` range syntax) and should be made to be.

Lastly, this commit adds support for parsing right-associative `<-` (left arrow)
operator with precedence higher than assignment as the operator for placement-in
feature.

---

This PR still needs various non-parser changes (e.g. src/grammar and tests) and I’m still working on these; the meat of the PR can already be reviewed, though, I think.

Please review carefully. I made sure that quirks I have discovered so far are preserved (see e.g. #29071) and am looking for more corner cases as I continue to work on tests et al, but there may be something I haven’t noticed or accounted for.

EDIT: I’m also not sure I managed to preserve all the semantics with the range operator inside non-trivial expressions since these are a mess at the moment. Crater runs would be nice.
  • Loading branch information
bors committed Oct 27, 2015
2 parents 8a72584 + 99f9bb1 commit e0e2627
Show file tree
Hide file tree
Showing 19 changed files with 525 additions and 223 deletions.
4 changes: 3 additions & 1 deletion src/grammar/RustLexer.g4
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ lexer grammar RustLexer;
tokens {
EQ, LT, LE, EQEQ, NE, GE, GT, ANDAND, OROR, NOT, TILDE, PLUS,
MINUS, STAR, SLASH, PERCENT, CARET, AND, OR, SHL, SHR, BINOP,
BINOPEQ, AT, DOT, DOTDOT, DOTDOTDOT, COMMA, SEMI, COLON,
BINOPEQ, LARROW, AT, DOT, DOTDOT, DOTDOTDOT, COMMA, SEMI, COLON,
MOD_SEP, RARROW, FAT_ARROW, LPAREN, RPAREN, LBRACKET, RBRACKET,
LBRACE, RBRACE, POUND, DOLLAR, UNDERSCORE, LIT_CHAR, LIT_BYTE,
LIT_INTEGER, LIT_FLOAT, LIT_STR, LIT_STR_RAW, LIT_BYTE_STR,
Expand Down Expand Up @@ -44,6 +44,7 @@ AND : '&' ;
OR : '|' ;
SHL : '<<' ;
SHR : '>>' ;
LARROW : '<-' ;

BINOP
: PLUS
Expand All @@ -56,6 +57,7 @@ BINOP
| OR
| SHL
| SHR
| LARROW
;

BINOPEQ : BINOP EQ ;
Expand Down
1 change: 1 addition & 0 deletions src/grammar/lexer.l
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@ r/# {
<str>\\[^n\nrt\\\x27\x220] { return -1; }
<str>(.|\n) { yymore(); }

\<- { return LARROW; }
-\> { return RARROW; }
- { return '-'; }
-= { return MINUSEQ; }
Expand Down
9 changes: 8 additions & 1 deletion src/grammar/parser-lalr.y
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ extern char *yytext;
%token DOTDOTDOT
%token MOD_SEP
%token RARROW
%token LARROW
%token FAT_ARROW
%token LIT_BYTE
%token LIT_CHAR
Expand Down Expand Up @@ -167,7 +168,8 @@ extern char *yytext;
// prefix_exprs
%precedence RETURN
%left '=' SHLEQ SHREQ MINUSEQ ANDEQ OREQ PLUSEQ STAREQ SLASHEQ CARETEQ PERCENTEQ
%right '=' SHLEQ SHREQ MINUSEQ ANDEQ OREQ PLUSEQ STAREQ SLASHEQ CARETEQ PERCENTEQ
%right LARROW
%left OROR
%left ANDAND
%left EQEQ NE
Expand Down Expand Up @@ -1316,6 +1318,7 @@ nonblock_expr
| RETURN expr { $$ = mk_node("ExprRet", 1, $2); }
| BREAK { $$ = mk_node("ExprBreak", 0); }
| BREAK lifetime { $$ = mk_node("ExprBreak", 1, $2); }
| nonblock_expr LARROW expr { $$ = mk_node("ExprInPlace", 2, $1, $3); }
| nonblock_expr '=' expr { $$ = mk_node("ExprAssign", 2, $1, $3); }
| nonblock_expr SHLEQ expr { $$ = mk_node("ExprAssignShl", 2, $1, $3); }
| nonblock_expr SHREQ expr { $$ = mk_node("ExprAssignShr", 2, $1, $3); }
Expand Down Expand Up @@ -1375,6 +1378,7 @@ expr
| RETURN expr { $$ = mk_node("ExprRet", 1, $2); }
| BREAK { $$ = mk_node("ExprBreak", 0); }
| BREAK ident { $$ = mk_node("ExprBreak", 1, $2); }
| expr LARROW expr { $$ = mk_node("ExprInPlace", 2, $1, $3); }
| expr '=' expr { $$ = mk_node("ExprAssign", 2, $1, $3); }
| expr SHLEQ expr { $$ = mk_node("ExprAssignShl", 2, $1, $3); }
| expr SHREQ expr { $$ = mk_node("ExprAssignShr", 2, $1, $3); }
Expand Down Expand Up @@ -1435,6 +1439,7 @@ nonparen_expr
| RETURN expr { $$ = mk_node("ExprRet", 1, $2); }
| BREAK { $$ = mk_node("ExprBreak", 0); }
| BREAK ident { $$ = mk_node("ExprBreak", 1, $2); }
| nonparen_expr LARROW nonparen_expr { $$ = mk_node("ExprInPlace", 2, $1, $3); }
| nonparen_expr '=' nonparen_expr { $$ = mk_node("ExprAssign", 2, $1, $3); }
| nonparen_expr SHLEQ nonparen_expr { $$ = mk_node("ExprAssignShl", 2, $1, $3); }
| nonparen_expr SHREQ nonparen_expr { $$ = mk_node("ExprAssignShr", 2, $1, $3); }
Expand Down Expand Up @@ -1495,6 +1500,7 @@ expr_nostruct
| RETURN expr { $$ = mk_node("ExprRet", 1, $2); }
| BREAK { $$ = mk_node("ExprBreak", 0); }
| BREAK ident { $$ = mk_node("ExprBreak", 1, $2); }
| expr_nostruct LARROW expr_nostruct { $$ = mk_node("ExprInPlace", 2, $1, $3); }
| expr_nostruct '=' expr_nostruct { $$ = mk_node("ExprAssign", 2, $1, $3); }
| expr_nostruct SHLEQ expr_nostruct { $$ = mk_node("ExprAssignShl", 2, $1, $3); }
| expr_nostruct SHREQ expr_nostruct { $$ = mk_node("ExprAssignShr", 2, $1, $3); }
Expand Down Expand Up @@ -1794,6 +1800,7 @@ unpaired_token
| GE { $$ = mk_atom(yytext); }
| ANDAND { $$ = mk_atom(yytext); }
| OROR { $$ = mk_atom(yytext); }
| LARROW { $$ = mk_atom(yytext); }
| SHLEQ { $$ = mk_atom(yytext); }
| SHREQ { $$ = mk_atom(yytext); }
| MINUSEQ { $$ = mk_atom(yytext); }
Expand Down
4 changes: 2 additions & 2 deletions src/grammar/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ use syntax::parse::lexer::TokenAndSpan;

fn parse_token_list(file: &str) -> HashMap<String, token::Token> {
fn id() -> token::Token {
token::Ident(ast::Ident::with_empty_ctxt(Name(0))), token::Plain)
token::Ident(ast::Ident::with_empty_ctxt(Name(0)), token::Plain)
}

let mut res = HashMap::new();
Expand Down Expand Up @@ -208,7 +208,7 @@ fn parse_antlr_token(s: &str, tokens: &HashMap<String, token::Token>, surrogate_
token::Literal(token::ByteStr(..), n) => token::Literal(token::ByteStr(nm), n),
token::Literal(token::ByteStrRaw(..), n) => token::Literal(token::ByteStrRaw(fix(content),
count(content)), n),
token::Ident(..) => token::Ident(ast::Ident::with_empty_ctxt(nm)),
token::Ident(..) => token::Ident(ast::Ident::with_empty_ctxt(nm),
token::ModName),
token::Lifetime(..) => token::Lifetime(ast::Ident::with_empty_ctxt(nm)),
ref t => t.clone()
Expand Down
1 change: 1 addition & 0 deletions src/librustc_lint/unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,7 @@ impl EarlyLintPass for UnusedParens {
ast::ExprRet(Some(ref value)) => (value, "`return` value", false),
ast::ExprAssign(_, ref value) => (value, "assigned value", false),
ast::ExprAssignOp(_, _, ref value) => (value, "assigned value", false),
ast::ExprInPlace(_, ref value) => (value, "emplacement value", false),
_ => return
};
self.check_unused_parens_core(cx, &**value, msg, struct_lit_needs_parens);
Expand Down
20 changes: 0 additions & 20 deletions src/libsyntax/ast_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,26 +242,6 @@ pub fn struct_field_visibility(field: ast::StructField) -> Visibility {
}
}

/// Maps a binary operator to its precedence
pub fn operator_prec(op: ast::BinOp_) -> usize {
match op {
// 'as' sits here with 12
BiMul | BiDiv | BiRem => 11,
BiAdd | BiSub => 10,
BiShl | BiShr => 9,
BiBitAnd => 8,
BiBitXor => 7,
BiBitOr => 6,
BiLt | BiLe | BiGe | BiGt | BiEq | BiNe => 3,
BiAnd => 2,
BiOr => 1
}
}

/// Precedence of the `as` operator, which is a binary operator
/// not appearing in the prior table.
pub const AS_PREC: usize = 12;

pub fn empty_generics() -> Generics {
Generics {
lifetimes: Vec::new(),
Expand Down
1 change: 1 addition & 0 deletions src/libsyntax/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ pub mod util {
#[cfg(test)]
pub mod parser_testing;
pub mod small_vector;
pub mod parser;
}

pub mod diagnostics {
Expand Down
Loading

0 comments on commit e0e2627

Please sign in to comment.