mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-26 14:43:24 +00:00
Refactor operator precedence code
Use functions instead of a dynamically created table to determine operator precedence. Gets rid of a FIXME in syntax::parse::prec. Change precedences from int to uint while we're at it, since don't use negative precedences.
This commit is contained in:
parent
1f92538e38
commit
8e15640ada
@ -344,6 +344,23 @@ fn is_self(d: ast::def) -> bool {
|
|||||||
_ { false }
|
_ { false }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc = "Maps a binary operator to its precedence"]
|
||||||
|
fn operator_prec(op: ast::binop) -> uint {
|
||||||
|
alt op {
|
||||||
|
mul | div | rem { 12u }
|
||||||
|
// 'as' sits between here with 11
|
||||||
|
add | subtract { 10u }
|
||||||
|
lsl | lsr | asr { 9u }
|
||||||
|
bitand { 8u }
|
||||||
|
bitxor { 7u }
|
||||||
|
bitor { 6u }
|
||||||
|
lt | le | ge | gt { 4u }
|
||||||
|
eq | ne { 3u }
|
||||||
|
and { 2u }
|
||||||
|
or { 1u }
|
||||||
|
}
|
||||||
|
}
|
||||||
// Local Variables:
|
// Local Variables:
|
||||||
// mode: rust
|
// mode: rust
|
||||||
// fill-column: 78;
|
// fill-column: 78;
|
||||||
|
@ -130,7 +130,6 @@ fn new_parser(sess: parse_sess, cfg: ast::crate_cfg, rdr: lexer::reader,
|
|||||||
mut buffer: [],
|
mut buffer: [],
|
||||||
mut restriction: parser::UNRESTRICTED,
|
mut restriction: parser::UNRESTRICTED,
|
||||||
reader: rdr,
|
reader: rdr,
|
||||||
binop_precs: prec::binop_prec_table(),
|
|
||||||
keywords: token::keyword_table(),
|
keywords: token::keyword_table(),
|
||||||
restricted_keywords: token::restricted_keyword_table()}
|
restricted_keywords: token::restricted_keyword_table()}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
Predicates on exprs and stmts that the pretty-printer and parser use
|
Predicates on exprs and stmts that the pretty-printer and parser use
|
||||||
*/
|
*/
|
||||||
|
import ast_util::*;
|
||||||
|
|
||||||
fn expr_requires_semi_to_be_stmt(e: @ast::expr) -> bool {
|
fn expr_requires_semi_to_be_stmt(e: @ast::expr) -> bool {
|
||||||
alt e.node {
|
alt e.node {
|
||||||
@ -31,14 +32,7 @@ fn stmt_ends_with_semi(stmt: ast::stmt) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn operator_prec(op: ast::binop) -> int {
|
fn need_parens(expr: @ast::expr, outer_prec: uint) -> bool {
|
||||||
for vec::each(*parse::prec::binop_prec_table()) {|spec|
|
|
||||||
if spec.op == op { ret spec.prec; }
|
|
||||||
}
|
|
||||||
core::unreachable();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn need_parens(expr: @ast::expr, outer_prec: int) -> bool {
|
|
||||||
alt expr.node {
|
alt expr.node {
|
||||||
ast::expr_binary(op, _, _) { operator_prec(op) < outer_prec }
|
ast::expr_binary(op, _, _) { operator_prec(op) < outer_prec }
|
||||||
ast::expr_cast(_, _) { parse::prec::as_prec < outer_prec }
|
ast::expr_cast(_, _) { parse::prec::as_prec < outer_prec }
|
||||||
|
@ -4,10 +4,10 @@ import std::map::{hashmap, str_hash};
|
|||||||
import token::{can_begin_expr, is_ident, is_plain_ident};
|
import token::{can_begin_expr, is_ident, is_plain_ident};
|
||||||
import codemap::{span,fss_none};
|
import codemap::{span,fss_none};
|
||||||
import util::interner;
|
import util::interner;
|
||||||
import ast_util::{spanned, mk_sp, ident_to_path};
|
import ast_util::{spanned, mk_sp, ident_to_path, operator_prec};
|
||||||
import ast::{node_id};
|
import ast::{node_id};
|
||||||
import lexer::reader;
|
import lexer::reader;
|
||||||
import prec::{op_spec, as_prec};
|
import prec::{as_prec, token_to_binop};
|
||||||
import attr::{parse_outer_attrs_or_ext,
|
import attr::{parse_outer_attrs_or_ext,
|
||||||
parse_inner_attrs_and_next,
|
parse_inner_attrs_and_next,
|
||||||
parse_outer_attributes,
|
parse_outer_attributes,
|
||||||
@ -57,7 +57,6 @@ type parser = @{
|
|||||||
mut buffer: [{tok: token::token, span: span}],
|
mut buffer: [{tok: token::token, span: span}],
|
||||||
mut restriction: restriction,
|
mut restriction: restriction,
|
||||||
reader: reader,
|
reader: reader,
|
||||||
binop_precs: @[op_spec],
|
|
||||||
keywords: hashmap<str, ()>,
|
keywords: hashmap<str, ()>,
|
||||||
restricted_keywords: hashmap<str, ()>
|
restricted_keywords: hashmap<str, ()>
|
||||||
};
|
};
|
||||||
@ -1040,26 +1039,31 @@ fn parse_prefix_expr(p: parser) -> pexpr {
|
|||||||
|
|
||||||
|
|
||||||
fn parse_binops(p: parser) -> @ast::expr {
|
fn parse_binops(p: parser) -> @ast::expr {
|
||||||
ret parse_more_binops(p, parse_prefix_expr(p), 0);
|
ret parse_more_binops(p, parse_prefix_expr(p), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_more_binops(p: parser, plhs: pexpr, min_prec: int) ->
|
fn parse_more_binops(p: parser, plhs: pexpr, min_prec: uint) ->
|
||||||
@ast::expr {
|
@ast::expr {
|
||||||
let lhs = to_expr(plhs);
|
let lhs = to_expr(plhs);
|
||||||
if expr_is_complete(p, plhs) { ret lhs; }
|
if expr_is_complete(p, plhs) { ret lhs; }
|
||||||
let peeked = p.token;
|
let peeked = p.token;
|
||||||
if peeked == token::BINOP(token::OR) &&
|
if peeked == token::BINOP(token::OR) &&
|
||||||
p.restriction == RESTRICT_NO_BAR_OP { ret lhs; }
|
p.restriction == RESTRICT_NO_BAR_OP { ret lhs; }
|
||||||
for vec::each(*p.binop_precs) {|cur|
|
let cur_opt = token_to_binop(peeked);
|
||||||
if cur.prec > min_prec && cur.tok == peeked {
|
alt cur_opt {
|
||||||
p.bump();
|
some(cur_op) {
|
||||||
let expr = parse_prefix_expr(p);
|
let cur_prec = operator_prec(cur_op);
|
||||||
let rhs = parse_more_binops(p, expr, cur.prec);
|
if cur_prec > min_prec {
|
||||||
p.get_id(); // see ast_util::op_expr_callee_id
|
p.bump();
|
||||||
let bin = mk_pexpr(p, lhs.span.lo, rhs.span.hi,
|
let expr = parse_prefix_expr(p);
|
||||||
ast::expr_binary(cur.op, lhs, rhs));
|
let rhs = parse_more_binops(p, expr, cur_prec);
|
||||||
ret parse_more_binops(p, bin, min_prec);
|
p.get_id(); // see ast_util::op_expr_callee_id
|
||||||
}
|
let bin = mk_pexpr(p, lhs.span.lo, rhs.span.hi,
|
||||||
|
ast::expr_binary(cur_op, lhs, rhs));
|
||||||
|
ret parse_more_binops(p, bin, min_prec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ {}
|
||||||
}
|
}
|
||||||
if as_prec > min_prec && eat_keyword(p, "as") {
|
if as_prec > min_prec && eat_keyword(p, "as") {
|
||||||
let rhs = parse_ty(p, true);
|
let rhs = parse_ty(p, true);
|
||||||
|
@ -1,40 +1,44 @@
|
|||||||
export as_prec;
|
export as_prec;
|
||||||
export unop_prec;
|
export unop_prec;
|
||||||
export binop_prec_table;
|
export token_to_binop;
|
||||||
export op_spec;
|
|
||||||
|
import token::*;
|
||||||
|
import token::token;
|
||||||
|
import ast::*;
|
||||||
|
|
||||||
#[doc = "Unary operators have higher precedence than binary"]
|
#[doc = "Unary operators have higher precedence than binary"]
|
||||||
const unop_prec: int = 100;
|
const unop_prec: uint = 100u;
|
||||||
|
|
||||||
#[doc = "
|
#[doc = "
|
||||||
Precedence of the `as` operator, which is a binary operator
|
Precedence of the `as` operator, which is a binary operator
|
||||||
but is not represented in the precedence table.
|
but is not represented in the precedence table.
|
||||||
"]
|
"]
|
||||||
const as_prec: int = 11;
|
const as_prec: uint = 11u;
|
||||||
|
|
||||||
type op_spec = {tok: token::token, op: ast::binop, prec: int};
|
#[doc = "Maps a token to a record specifying the corresponding binary
|
||||||
|
operator and its precedence"]
|
||||||
// FIXME make this a const, don't store it in parser state
|
fn token_to_binop(tok: token) -> option<ast::binop> {
|
||||||
#[doc = "The precedence of binary operators"]
|
alt tok {
|
||||||
fn binop_prec_table() -> @[op_spec] {
|
BINOP(STAR) { some(mul) }
|
||||||
ret @[{tok: token::BINOP(token::STAR), op: ast::mul, prec: 12},
|
BINOP(SLASH) { some(div) }
|
||||||
{tok: token::BINOP(token::SLASH), op: ast::div, prec: 12},
|
BINOP(PERCENT) { some(rem) }
|
||||||
{tok: token::BINOP(token::PERCENT), op: ast::rem, prec: 12},
|
// 'as' sits between here with 11
|
||||||
// 'as' sits between here with 11
|
BINOP(PLUS) { some(add) }
|
||||||
{tok: token::BINOP(token::PLUS), op: ast::add, prec: 10},
|
BINOP(MINUS) { some(subtract) }
|
||||||
{tok: token::BINOP(token::MINUS), op: ast::subtract, prec: 10},
|
BINOP(LSL) { some(lsl) }
|
||||||
{tok: token::BINOP(token::LSL), op: ast::lsl, prec: 9},
|
BINOP(LSR) { some(lsr) }
|
||||||
{tok: token::BINOP(token::LSR), op: ast::lsr, prec: 9},
|
BINOP(ASR) { some(asr) }
|
||||||
{tok: token::BINOP(token::ASR), op: ast::asr, prec: 9},
|
BINOP(AND) { some(bitand) }
|
||||||
{tok: token::BINOP(token::AND), op: ast::bitand, prec: 8},
|
BINOP(CARET) { some(bitxor) }
|
||||||
{tok: token::BINOP(token::CARET), op: ast::bitxor, prec: 7},
|
BINOP(OR) { some(bitor) }
|
||||||
{tok: token::BINOP(token::OR), op: ast::bitor, prec: 6},
|
LT { some(lt) }
|
||||||
{tok: token::LT, op: ast::lt, prec: 4},
|
LE { some(le) }
|
||||||
{tok: token::LE, op: ast::le, prec: 4},
|
GE { some(ge) }
|
||||||
{tok: token::GE, op: ast::ge, prec: 4},
|
GT { some(gt) }
|
||||||
{tok: token::GT, op: ast::gt, prec: 4},
|
EQEQ { some(eq) }
|
||||||
{tok: token::EQEQ, op: ast::eq, prec: 3},
|
NE { some(ne) }
|
||||||
{tok: token::NE, op: ast::ne, prec: 3},
|
ANDAND { some(and) }
|
||||||
{tok: token::ANDAND, op: ast::and, prec: 2},
|
OROR { some(or) }
|
||||||
{tok: token::OROR, op: ast::or, prec: 1}];
|
_ { none }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import pp::{break_offset, word, printer,
|
|||||||
space, zerobreak, hardbreak, breaks, consistent,
|
space, zerobreak, hardbreak, breaks, consistent,
|
||||||
inconsistent, eof};
|
inconsistent, eof};
|
||||||
import diagnostic;
|
import diagnostic;
|
||||||
|
import ast_util::operator_prec;
|
||||||
|
|
||||||
// The ps is stored here to prevent recursive type.
|
// The ps is stored here to prevent recursive type.
|
||||||
enum ann_node {
|
enum ann_node {
|
||||||
@ -936,7 +937,7 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
|
|||||||
print_op_maybe_parens(s, lhs, prec);
|
print_op_maybe_parens(s, lhs, prec);
|
||||||
space(s.s);
|
space(s.s);
|
||||||
word_space(s, ast_util::binop_to_str(op));
|
word_space(s, ast_util::binop_to_str(op));
|
||||||
print_op_maybe_parens(s, rhs, prec + 1);
|
print_op_maybe_parens(s, rhs, prec + 1u);
|
||||||
}
|
}
|
||||||
ast::expr_unary(op, expr) {
|
ast::expr_unary(op, expr) {
|
||||||
word(s.s, ast_util::unop_to_str(op));
|
word(s.s, ast_util::unop_to_str(op));
|
||||||
@ -1517,7 +1518,7 @@ fn print_view_item(s: ps, item: @ast::view_item) {
|
|||||||
end(s); // end outer head-block
|
end(s); // end outer head-block
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_op_maybe_parens(s: ps, expr: @ast::expr, outer_prec: int) {
|
fn print_op_maybe_parens(s: ps, expr: @ast::expr, outer_prec: uint) {
|
||||||
let add_them = need_parens(expr, outer_prec);
|
let add_them = need_parens(expr, outer_prec);
|
||||||
if add_them { popen(s); }
|
if add_them { popen(s); }
|
||||||
print_expr(s, expr);
|
print_expr(s, expr);
|
||||||
|
Loading…
Reference in New Issue
Block a user