Update the parser to accept the new syntax

This commit is contained in:
Marijn Haverbeke 2011-07-27 09:13:00 +02:00
parent 300eb30113
commit 66c1ca857b

View File

@ -155,6 +155,7 @@ fn bad_expr_word_table() -> hashmap[str, ()] {
words.insert("do", ());
words.insert("alt", ());
words.insert("for", ());
words.insert("each", ());
words.insert("break", ());
words.insert("cont", ());
words.insert("put", ());
@ -221,6 +222,11 @@ fn parse_value_ident(&parser p) -> ast::ident {
ret parse_ident(p);
}
fn eat(&parser p, &token::token tok) -> bool {
ret if p.peek() == tok { p.bump(); true }
else { false };
}
fn is_word(&parser p, &str word) -> bool {
ret alt (p.peek()) {
case (token::IDENT(?sid, false)) { str::eq(word, p.get_str(sid)) }
@ -262,16 +268,16 @@ fn check_bad_word(&parser p) {
fn parse_ty_fn(ast::proto proto, &parser p, uint lo) -> ast::ty_ {
fn parse_fn_input_ty(&parser p) -> ast::ty_arg {
auto lo = p.get_lo_pos();
// Ignore arg name, if present
if is_plain_ident(p) && p.look_ahead(1u) == token::COLON {
p.bump(); p.bump();
}
auto mode = ast::val;
if (p.peek() == token::BINOP(token::AND)) {
p.bump();
mode = ast::alias(eat_word(p, "mutable"));
}
auto t = parse_ty(p);
alt (p.peek()) {
case (token::IDENT(_, _)) { p.bump();/* ignore param name */ }
case (_) {/* no param name present */ }
}
ret spanned(lo, t.span.hi, rec(mode=mode, ty=t));
}
auto lo = p.get_lo_pos();
@ -342,14 +348,6 @@ fn parse_mt(&parser p) -> ast::mt {
}
fn parse_ty_field(&parser p) -> ast::ty_field {
auto lo = p.get_lo_pos();
auto mt = parse_mt(p);
auto id = parse_ident(p);
ret spanned(lo, mt.ty.span.hi, rec(ident=id, mt=mt));
}
// FIXME rename to parse_ty_field once the other one is dropped
fn parse_ty_field_modern(&parser p) -> ast::ty_field {
auto lo = p.get_lo_pos();
auto mut = parse_mutability(p);
auto id = parse_ident(p);
@ -555,7 +553,7 @@ fn parse_ty(&parser p) -> @ast::ty {
t = ast::ty_ptr(mt);
} else if (p.peek() == token::LBRACE) {
auto elems = parse_seq(token::LBRACE, token::RBRACE,
some(token::COMMA), parse_ty_field_modern, p);
some(token::COMMA), parse_ty_field, p);
hi = elems.span.hi;
t = ast::ty_rec(elems.node);
if (p.peek() == token::COLON) {
@ -568,20 +566,6 @@ fn parse_ty(&parser p) -> @ast::ty {
t = ast::ty_vec(parse_mt(p));
hi = p.get_hi_pos();
expect(p, token::RBRACKET);
} else if (eat_word(p, "rec")) {
auto elems =
parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
parse_ty_field, p);
hi = elems.span.hi;
// possible constrs
// FIXME: something seems dodgy or at least repetitive
// about how constrained types get parsed
t = ast::ty_rec(elems.node);
if (p.peek() == token::COLON) {
p.bump();
t = ast::ty_constr(@spanned(lo, hi, t),
parse_type_constraints(p));
}
} else if (eat_word(p, "fn")) {
auto flo = p.get_last_lo_pos();
t = parse_ty_fn(ast::proto_fn, p, flo);
@ -621,12 +605,12 @@ fn parse_ty(&parser p) -> @ast::ty {
fn parse_arg(&parser p) -> ast::arg {
let ast::mode m = ast::val;
if (p.peek() == token::BINOP(token::AND)) {
p.bump();
let ast::ident i = parse_value_ident(p);
expect(p, token::COLON);
if eat(p, token::BINOP(token::AND)) {
m = ast::alias(eat_word(p, "mutable"));
}
let @ast::ty t = parse_ty(p);
let ast::ident i = parse_value_ident(p);
ret rec(mode=m, ty=t, ident=i, id=p.get_id());
}
@ -710,6 +694,10 @@ fn is_ident(token::token t) -> bool {
ret false;
}
fn is_plain_ident(&parser p) -> bool {
ret alt p.peek() { token::IDENT(_, false) { true } _ { false } };
}
fn parse_path(&parser p) -> ast::path {
auto lo = p.get_lo_pos();
auto hi = lo;
@ -806,8 +794,7 @@ fn parse_bottom_expr(&parser p) -> @ast::expr {
} else if (p.peek() == token::LBRACE) {
p.bump();
if (is_word(p, "mutable") ||
alt p.peek() { token::IDENT(_, false) { true } _ { false } } &&
p.look_ahead(1u) == token::COLON) {
is_plain_ident(p) && p.look_ahead(1u) == token::COLON) {
auto fields = ~[parse_field(p, token::COLON)];
auto base = none;
while p.peek() != token::RBRACE {
@ -915,27 +902,6 @@ fn parse_bottom_expr(&parser p) -> @ast::expr {
let ast::anon_obj ob =
rec(fields=fields, methods=meths, with_obj=with_obj);
ex = ast::expr_anon_obj(ob);
} else if (eat_word(p, "rec")) {
expect(p, token::LPAREN);
auto fields = ~[parse_field(p, token::EQ)];
auto more = true;
auto base = none;
while (more) {
if (p.peek() == token::RPAREN) {
hi = p.get_hi_pos();
p.bump();
more = false;
} else if (eat_word(p, "with")) {
base = some(parse_expr(p));
hi = p.get_hi_pos();
expect(p, token::RPAREN);
more = false;
} else if (p.peek() == token::COMMA) {
p.bump();
fields += ~[parse_field(p, token::EQ)];
} else { unexpected(p, p.peek()); }
}
ex = ast::expr_rec(fields, base);
} else if (eat_word(p, "bind")) {
auto e = parse_expr_res(p, RESTRICT_NO_CALL_EXPRS);
fn parse_expr_opt(&parser p) -> option::t[@ast::expr] {
@ -1349,25 +1315,15 @@ fn parse_else_expr(&parser p) -> @ast::expr {
}
}
fn parse_head_local(&parser p) -> @ast::local {
if (eat_word(p, "auto")) {
ret parse_auto_local(p);
} else {
ret parse_typed_local(p);
}
}
fn parse_for_expr(&parser p) -> @ast::expr {
auto lo = p.get_last_lo_pos();
auto is_each = eat_word(p, "each");
expect(p, token::LPAREN);
auto decl = parse_head_local(p);
auto decl = parse_local(p, false);
expect_word(p, "in");
auto seq = parse_expr(p);
expect(p, token::RPAREN);
auto body = parse_block(p);
auto hi = body.span.hi;
if (is_each) {
if is_each {
ret mk_expr(p, lo, hi, ast::expr_for_each(decl, seq, body));
} else {
ret mk_expr(p, lo, hi, ast::expr_for(decl, seq, body));
@ -1483,21 +1439,6 @@ fn parse_pat(&parser p) -> @ast::pat {
p.bump();
pat = ast::pat_wild;
}
case (token::QUES) {
p.bump();
alt (p.peek()) {
case (token::IDENT(?id, _)) {
hi = p.get_hi_pos();
p.bump();
pat = ast::pat_bind(p.get_str(id));
}
case (?tok) {
p.fatal("expected identifier after '?' in pattern but " +
"found " + token::to_str(p.get_reader(), tok));
fail;
}
}
}
case (token::AT) {
p.bump();
auto sub = parse_pat(p);
@ -1548,6 +1489,15 @@ fn parse_pat(&parser p) -> @ast::pat {
auto lit = parse_lit(p);
hi = lit.span.hi;
pat = ast::pat_lit(@lit);
} else if (is_plain_ident(p) &&
alt p.look_ahead(1u) {
token::DOT | token::LPAREN | token::LBRACKET {
false
}
_ { true }
}) {
hi = p.get_hi_pos();
pat = ast::pat_bind(parse_ident(p));
} else {
auto tag_path = parse_path_and_ty_param_substs(p);
hi = tag_path.span.hi;
@ -1559,7 +1509,11 @@ fn parse_pat(&parser p) -> @ast::pat {
args = a.node;
hi = a.span.hi;
}
case (_) { args = ~[]; }
case (token::DOT) {
args = ~[];
p.bump();
}
case (_) { expect(p, token::LPAREN); fail; }
}
pat = ast::pat_tag(tag_path, args);
}
@ -1568,81 +1522,30 @@ fn parse_pat(&parser p) -> @ast::pat {
ret @rec(id=p.get_id(), node=pat, span=rec(lo=lo, hi=hi));
}
fn parse_local_full(&option::t[@ast::ty] tyopt, &parser p)
-> @ast::local {
fn parse_local(&parser p, bool allow_init) -> @ast::local {
auto lo = p.get_lo_pos();
auto ident = parse_value_ident(p);
auto init = parse_initializer(p);
ret @spanned(lo, p.get_hi_pos(),
rec(ty=tyopt,
infer=false,
ident=ident,
init=init,
id=p.get_id()));
auto ty = none;
if eat(p, token::COLON) {
ty = some(parse_ty(p));
}
auto init = if allow_init { parse_initializer(p) }
else { none };
ret @spanned(lo, p.get_last_hi_pos(),
rec(ty=ty, infer=false, ident=ident,
init=init, id=p.get_id()));
}
fn parse_typed_local(&parser p) -> @ast::local {
auto ty = parse_ty(p);
ret parse_local_full(some(ty), p);
}
fn parse_auto_local(&parser p) -> @ast::local {
ret parse_local_full(none, p);
}
// FIXME simplify when old syntax is no longer supported
fn parse_let(&parser p) -> @ast::decl {
if alt p.peek() { token::IDENT(_, false) { true } _ { false } } {
alt p.look_ahead(1u) {
token::COLON | token::SEMI | token::COMMA | token::EQ |
token::LARROW {
ret parse_let_modern(p);
}
_ {}
}
}
auto lo = p.get_last_lo_pos();
auto locals = ~[parse_typed_local(p)];
while p.peek() == token::COMMA {
p.bump();
locals += ~[parse_typed_local(p)];
}
ret @spanned(lo, p.get_hi_pos(), ast::decl_local(locals));
}
fn parse_let_modern(&parser p) -> @ast::decl {
fn parse_local(&parser p) -> @ast::local {
auto lo = p.get_lo_pos();
auto ident = parse_value_ident(p);
auto ty = none;
if p.peek() == token::COLON {
p.bump();
ty = some(parse_ty(p));
}
auto init = parse_initializer(p);
ret @spanned(lo, p.get_last_hi_pos(),
rec(ty=ty, infer=false, ident=ident,
init=init, id=p.get_id()));
}
auto lo = p.get_lo_pos();
auto locals = ~[parse_local(p)];
auto locals = ~[parse_local(p, true)];
while p.peek() == token::COMMA {
p.bump();
locals += ~[parse_local(p)];
locals += ~[parse_local(p, true)];
}
ret @spanned(lo, p.get_last_hi_pos(), ast::decl_local(locals));
}
fn parse_auto(&parser p) -> @ast::decl {
auto lo = p.get_last_lo_pos();
auto locals = ~[parse_auto_local(p)];
while p.peek() == token::COMMA {
p.bump();
locals += ~[parse_auto_local(p)];
}
ret @spanned(lo, p.get_hi_pos(), ast::decl_local(locals));
}
fn parse_stmt(&parser p) -> @ast::stmt {
if (p.get_file_type() == SOURCE_FILE) {
ret parse_source_stmt(p);
@ -1660,9 +1563,6 @@ fn parse_source_stmt(&parser p) -> @ast::stmt {
if (eat_word(p, "let")) {
auto decl = parse_let(p);
ret @spanned(lo, decl.span.hi, ast::stmt_decl(decl, p.get_id()));
} else if (eat_word(p, "auto")) {
auto decl = parse_auto(p);
ret @spanned(lo, decl.span.hi, ast::stmt_decl(decl, p.get_id()));
} else {
auto item_attrs;
@ -1850,11 +1750,11 @@ fn parse_ty_params(&parser p) -> ast::ty_param[] {
fn parse_fn_decl(&parser p, ast::purity purity) -> ast::fn_decl {
let ast::spanned[ast::arg[]] inputs =
parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
parse_arg, p);
parse_arg, p);
let ty_or_bang rslt;
// Use the args list to translate each bound variable
// mentioned in a constraint to an arg index.
// Seems weird to do this in the parser, but I'm not sure how else to.
// Use the args list to translate each bound variable
// mentioned in a constraint to an arg index.
// Seems weird to do this in the parser, but I'm not sure how else to.
auto constrs = ~[];
if (p.peek() == token::COLON) {
p.bump();
@ -1917,15 +1817,17 @@ fn parse_item_fn_or_iter(&parser p, ast::purity purity, ast::proto proto,
fn parse_obj_field(&parser p) -> ast::obj_field {
auto mut = parse_mutability(p);
auto ty = parse_ty(p);
auto ident = parse_value_ident(p);
expect(p, token::COLON);
auto ty = parse_ty(p);
ret rec(mut=mut, ty=ty, ident=ident, id=p.get_id());
}
fn parse_anon_obj_field(&parser p) -> ast::anon_obj_field {
auto mut = parse_mutability(p);
auto ty = parse_ty(p);
auto ident = parse_value_ident(p);
expect(p, token::COLON);
auto ty = parse_ty(p);
expect(p, token::EQ);
auto expr = parse_expr(p);
ret rec(mut=mut, ty=ty, expr=expr, ident=ident, id=p.get_id());
@ -1988,8 +1890,9 @@ fn parse_item_res(&parser p, ast::layer lyr, &ast::attribute[] attrs) ->
auto ident = parse_value_ident(p);
auto ty_params = parse_ty_params(p);
expect(p, token::LPAREN);
auto t = parse_ty(p);
auto arg_ident = parse_value_ident(p);
expect(p, token::COLON);
auto t = parse_ty(p);
expect(p, token::RPAREN);
auto dtor = parse_block(p);
auto decl = rec(inputs=~[rec(mode=ast::alias(false), ty=t,
@ -2029,8 +1932,9 @@ fn parse_mod_items(&parser p, token::token term,
fn parse_item_const(&parser p, &ast::attribute[] attrs) -> @ast::item {
auto lo = p.get_last_lo_pos();
auto ty = parse_ty(p);
auto id = parse_value_ident(p);
expect(p, token::COLON);
auto ty = parse_ty(p);
expect(p, token::EQ);
auto e = parse_expr(p);
auto hi = p.get_hi_pos();