aboutsummaryrefslogtreecommitdiff
path: root/src/comp/front/parser.rs
diff options
context:
space:
mode:
authorMarijn Haverbeke <[email protected]>2011-05-13 21:30:08 +0200
committerMarijn Haverbeke <[email protected]>2011-05-13 22:00:13 +0200
commit57ffa2a487ef12a4abf538efc2dd8192ca308271 (patch)
treef3a82a1076c93c6ad6200391cc838cf2e7e6999d /src/comp/front/parser.rs
parentrustc: Fix the type of node_types; stub the write_type function (diff)
downloadrust-57ffa2a487ef12a4abf538efc2dd8192ca308271.tar.xz
rust-57ffa2a487ef12a4abf538efc2dd8192ca308271.zip
Make the parser more careful about keywords
Keywords are now only recognized in contexts where they are valid. The lexer no longer recognizes them, all words are lexed as IDENT tokens, that get interpreted by the parser.
Diffstat (limited to 'src/comp/front/parser.rs')
-rw-r--r--src/comp/front/parser.rs1406
1 files changed, 606 insertions, 800 deletions
diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs
index 5292c49c..2cb00bcd 100644
--- a/src/comp/front/parser.rs
+++ b/src/comp/front/parser.rs
@@ -35,6 +35,7 @@ state type parser =
fn get_span() -> common::span;
fn get_lo_pos() -> uint;
fn get_hi_pos() -> uint;
+ fn get_last_lo_pos() -> uint;
fn next_def_id() -> ast::def_id;
fn set_def(ast::def_num);
fn get_prec_table() -> vec[op_spec];
@@ -56,6 +57,7 @@ fn new_parser(session::session sess,
mutable token::token tok,
mutable uint lo,
mutable uint hi,
+ mutable uint last_lo,
mutable ast::def_num def,
mutable restriction res,
ast::crate_num crate,
@@ -70,6 +72,7 @@ fn new_parser(session::session sess,
fn bump() {
// log rdr.get_filename()
// + ":" + common::istr(lo.line as int);
+ last_lo = lo;
tok = lexer::next_token(rdr);
lo = rdr.get_mark_chpos();
hi = rdr.get_chpos();
@@ -94,6 +97,7 @@ fn new_parser(session::session sess,
fn get_span() -> common::span { ret rec(lo=lo, hi=hi); }
fn get_lo_pos() -> uint { ret lo; }
fn get_hi_pos() -> uint { ret hi; }
+ fn get_last_lo_pos() -> uint { ret last_lo; }
fn next_def_id() -> ast::def_id {
def += 1;
@@ -151,8 +155,8 @@ fn new_parser(session::session sess,
lexer::consume_any_whitespace(rdr);
auto npos = rdr.get_chpos();
ret stdio_parser(sess, env, ftype, lexer::next_token(rdr),
- npos, npos, initial_def._1, UNRESTRICTED, initial_def._0,
- rdr, prec_table(), next_ann);
+ npos, npos, npos, initial_def._1, UNRESTRICTED,
+ initial_def._0, rdr, prec_table(), next_ann);
}
fn unexpected(parser p, token::token t) {
@@ -212,6 +216,30 @@ fn parse_str_lit_or_env_ident(parser p) -> ast::ident {
}
}
+fn is_word(&parser p, &str word) -> bool {
+ ret alt (p.peek()) {
+ case (token::IDENT(?sid)) { _str::eq(word, p.get_str(sid)) }
+ case (_) { false }
+ };
+}
+fn eat_word(&parser p, &str word) -> bool {
+ alt (p.peek()) {
+ case (token::IDENT(?sid)) {
+ if (_str::eq(word, p.get_str(sid))) {
+ p.bump();
+ ret true;
+ } else { ret false; }
+
+ }
+ case (_) { ret false; }
+ }
+}
+fn expect_word(&parser p, &str word) {
+ if (!eat_word(p, word)) {
+ p.err("expecting " + word + ", found " +
+ token::to_str(p.get_reader(), p.peek()));
+ }
+}
fn parse_ty_fn(ast::proto proto, parser p, uint lo)
-> ast::ty_ {
@@ -221,8 +249,7 @@ fn parse_ty_fn(ast::proto proto, parser p, uint lo)
p.bump();
mode = ast::alias;
- if (p.peek() == token::MUTABLE) {
- p.bump();
+ if (eat_word(p, "mutable")) {
// TODO: handle mutable alias args
}
} else {
@@ -261,17 +288,13 @@ fn parse_ty_fn(ast::proto proto, parser p, uint lo)
}
fn parse_proto(parser p) -> ast::proto {
- alt (p.peek()) {
- case (token::ITER) { p.bump(); ret ast::proto_iter; }
- case (token::FN) { p.bump(); ret ast::proto_fn; }
- case (token::PRED) { p.bump(); ret ast::proto_fn; }
- case (?t) { unexpected(p, t); }
- }
- fail;
+ if (eat_word(p, "iter")) { ret ast::proto_iter; }
+ else if (eat_word(p, "fn")) { ret ast::proto_fn; }
+ else if (eat_word(p, "pred")) { ret ast::proto_fn; }
+ else { unexpected(p, p.peek()); }
}
fn parse_ty_obj(parser p, &mutable uint hi) -> ast::ty_ {
- expect(p, token::OBJ);
fn parse_method_sig(parser p) -> ast::ty_method {
auto flo = p.get_lo_pos();
@@ -367,130 +390,105 @@ fn parse_ty(parser p) -> @ast::ty {
// FIXME: do something with this
let ast::layer lyr = parse_layer(p);
- alt (p.peek()) {
- case (token::BOOL) { p.bump(); t = ast::ty_bool; }
- case (token::INT) { p.bump(); t = ast::ty_int; }
- case (token::UINT) { p.bump(); t = ast::ty_uint; }
- case (token::FLOAT) { p.bump(); t = ast::ty_float; }
- case (token::STR) { p.bump(); t = ast::ty_str; }
- case (token::CHAR) { p.bump(); t = ast::ty_char; }
- case (token::MACH(?tm)) { p.bump(); t = ast::ty_machine(tm); }
-
- case (token::LPAREN) {
- p.bump();
- alt (p.peek()) {
- case (token::RPAREN) {
- hi = p.get_hi_pos();
- p.bump();
- t = ast::ty_nil;
- }
- case (_) {
- t = parse_ty(p).node;
- hi = p.get_hi_pos();
- expect(p, token::RPAREN);
- }
+ let ast::ty t;
+ if (eat_word(p, "bool")) { t = ast::ty_bool; }
+ else if (eat_word(p, "int")) { t = ast::ty_int; }
+ else if (eat_word(p, "uint")) { t = ast::ty_uint; }
+ else if (eat_word(p, "float")) { t = ast::ty_float; }
+ else if (eat_word(p, "str")) { t = ast::ty_str; }
+ else if (eat_word(p, "char")) { t = ast::ty_char; }
+ else if (eat_word(p, "i8")) { t = ast::ty_machine(common::ty_i8); }
+ else if (eat_word(p, "i16")) { t = ast::ty_machine(common::ty_i16); }
+ else if (eat_word(p, "i32")) { t = ast::ty_machine(common::ty_i32); }
+ else if (eat_word(p, "i64")) { t = ast::ty_machine(common::ty_i64); }
+ else if (eat_word(p, "u8")) { t = ast::ty_machine(common::ty_u8); }
+ else if (eat_word(p, "u16")) { t = ast::ty_machine(common::ty_u16); }
+ else if (eat_word(p, "u32")) { t = ast::ty_machine(common::ty_u32); }
+ else if (eat_word(p, "u64")) { t = ast::ty_machine(common::ty_u64); }
+ else if (eat_word(p, "f32")) { t = ast::ty_machine(common::ty_f32); }
+ else if (eat_word(p, "f64")) { t = ast::ty_machine(common::ty_f64); }
+ else if (p.peek() == token::LPAREN) {
+ p.bump();
+ alt (p.peek()) {
+ case (token::RPAREN) {
+ hi = p.get_hi_pos();
+ p.bump();
+ t = ast::ty_nil;
}
- }
-
- case (token::AT) {
- p.bump();
- auto mt = parse_mt(p);
- hi = mt.ty.span.hi;
- t = ast::ty_box(mt);
- }
-
- case (token::VEC) {
- p.bump();
- expect(p, token::LBRACKET);
- t = ast::ty_vec(parse_mt(p));
- hi = p.get_hi_pos();
- expect(p, token::RBRACKET);
- }
-
- case (token::TUP) {
- p.bump();
- auto f = parse_mt; // FIXME: trans_const_lval bug
- auto elems = parse_seq[ast::mt] (token::LPAREN,
- token::RPAREN,
- some(token::COMMA), f, p);
- hi = elems.span.hi;
- t = ast::ty_tup(elems.node);
- }
-
- case (token::REC) {
- p.bump();
- auto f = parse_ty_field; // FIXME: trans_const_lval bug
- auto elems =
- parse_seq[ast::ty_field](token::LPAREN,
- token::RPAREN,
- some(token::COMMA),
- f, p);
- hi = elems.span.hi;
- t = ast::ty_rec(elems.node);
- }
-
- case (token::FN) {
- auto flo = p.get_lo_pos();
- p.bump();
- t = parse_ty_fn(ast::proto_fn, p, flo);
- alt (t) {
- case (ast::ty_fn(_, _, ?out)) {
- hi = out.span.hi;
- }
+ case (_) {
+ t = parse_ty(p).node;
+ hi = p.get_hi_pos();
+ expect(p, token::RPAREN);
}
}
-
- case (token::ITER) {
- auto flo = p.get_lo_pos();
- p.bump();
- t = parse_ty_fn(ast::proto_iter, p, flo);
- alt (t) {
- case (ast::ty_fn(_, _, ?out)) {
- hi = out.span.hi;
- }
+ } else if (p.peek() == token::AT) {
+ p.bump();
+ auto mt = parse_mt(p);
+ hi = mt.ty.span.hi;
+ t = ast::ty_box(mt);
+ } else if (eat_word(p, "vec")) {
+ expect(p, token::LBRACKET);
+ t = ast::ty_vec(parse_mt(p));
+ hi = p.get_hi_pos();
+ expect(p, token::RBRACKET);
+ } else if (eat_word(p, "tup")) {
+ auto f = parse_mt; // FIXME: trans_const_lval bug
+ auto elems = parse_seq[ast::mt] (token::LPAREN,
+ token::RPAREN,
+ some(token::COMMA), f, p);
+ hi = elems.span.hi;
+ t = ast::ty_tup(elems.node);
+ } else if (eat_word(p, "rec")) {
+ auto f = parse_ty_field; // FIXME: trans_const_lval bug
+ auto elems =
+ parse_seq[ast::ty_field](token::LPAREN,
+ token::RPAREN,
+ some(token::COMMA),
+ f, p);
+ hi = elems.span.hi;
+ t = ast::ty_rec(elems.node);
+ } else if (eat_word(p, "fn")) {
+ auto flo = p.get_last_lo_pos();
+ t = parse_ty_fn(ast::proto_fn, p, flo);
+ alt (t) {
+ case (ast::ty_fn(_, _, ?out)) {
+ hi = out.span.hi;
}
}
-
- case (token::OBJ) {
- t = parse_ty_obj(p, hi);
- }
-
- case (token::PORT) {
- p.bump();
- expect(p, token::LBRACKET);
- t = ast::ty_port(parse_ty(p));
- hi = p.get_hi_pos();
- expect(p, token::RBRACKET);
- }
-
- case (token::CHAN) {
- p.bump();
- expect(p, token::LBRACKET);
- t = ast::ty_chan(parse_ty(p));
- hi = p.get_hi_pos();
- expect(p, token::RBRACKET);
- }
-
- case (token::IDENT(_)) {
- auto path = parse_path(p);
- t = ast::ty_path(path, p.get_ann());
- hi = path.span.hi;
- }
-
- case (token::MUTABLE) {
- p.bump();
- p.get_session().span_warn(p.get_span(),
- "ignoring deprecated 'mutable' type constructor");
- auto typ = parse_ty(p);
- t = typ.node;
- hi = typ.span.hi;
- }
-
- case (_) {
- p.err("expecting type");
- t = ast::ty_nil;
- fail;
+ } else if (eat_word(p, "iter")) {
+ auto flo = p.get_last_lo_pos();
+ t = parse_ty_fn(ast::proto_iter, p, flo);
+ alt (t) {
+ case (ast::ty_fn(_, _, ?out)) {
+ hi = out.span.hi;
+ }
}
+ } else if (eat_word(p, "obj")) {
+ t = parse_ty_obj(p, hi);
+ } else if (eat_word(p, "port")) {
+ expect(p, token::LBRACKET);
+ t = ast::ty_port(parse_ty(p));
+ hi = p.get_hi_pos();
+ expect(p, token::RBRACKET);
+ } else if (eat_word(p, "chan")) {
+ expect(p, token::LBRACKET);
+ t = ast::ty_chan(parse_ty(p));
+ hi = p.get_hi_pos();
+ expect(p, token::RBRACKET);
+ } else if (eat_word(p, "mutable")) {
+ p.get_session().span_warn(p.get_span(),
+ "ignoring deprecated 'mutable' type constructor");
+ auto typ = parse_ty(p);
+ t = typ.node;
+ hi = typ.span.hi;
+ } else if (is_ident(p.peek())) {
+ auto path = parse_path(p);
+ t = ast::ty_path(path, p.get_ann());
+ hi = path.span.hi;
+ } else {
+ p.err("expecting type");
+ t = ast::ty_nil;
+ fail;
}
ret parse_ty_constrs(@spanned(lo, hi, t), p);
@@ -502,10 +500,8 @@ fn parse_arg(parser p) -> ast::arg {
m = ast::alias;
p.bump();
- if (p.peek() == token::MUTABLE) {
- // TODO: handle mutable alias args
- p.bump();
- }
+ // TODO: handle mutable alias args
+ eat_word(p, "mutable");
}
let @ast::ty t = parse_ty(p);
let ast::ident i = parse_ident(p);
@@ -555,41 +551,43 @@ fn parse_seq[T](token::token bra,
fn parse_lit(parser p) -> ast::lit {
auto sp = p.get_span();
let ast::lit_ lit = ast::lit_nil;
- alt (p.peek()) {
- case (token::LIT_INT(?i)) {
- p.bump();
- lit = ast::lit_int(i);
- }
- case (token::LIT_UINT(?u)) {
- p.bump();
- lit = ast::lit_uint(u);
- }
- case (token::LIT_FLOAT(?s)) {
- p.bump();
- lit = ast::lit_float(p.get_str(s));
- }
- case (token::LIT_MACH_INT(?tm, ?i)) {
- p.bump();
- lit = ast::lit_mach_int(tm, i);
- }
- case (token::LIT_MACH_FLOAT(?tm, ?s)) {
- p.bump();
- lit = ast::lit_mach_float(tm, p.get_str(s));
- }
- case (token::LIT_CHAR(?c)) {
- p.bump();
- lit = ast::lit_char(c);
- }
- case (token::LIT_BOOL(?b)) {
- p.bump();
- lit = ast::lit_bool(b);
- }
- case (token::LIT_STR(?s)) {
- p.bump();
- lit = ast::lit_str(p.get_str(s));
- }
- case (?t) {
- unexpected(p, t);
+ if (eat_word(p, "true")) {
+ lit = ast::lit_bool(true);
+ } else if (eat_word(p, "false")) {
+ lit = ast::lit_bool(false);
+ } else {
+ alt (p.peek()) {
+ case (token::LIT_INT(?i)) {
+ p.bump();
+ lit = ast::lit_int(i);
+ }
+ case (token::LIT_UINT(?u)) {
+ p.bump();
+ lit = ast::lit_uint(u);
+ }
+ case (token::LIT_FLOAT(?s)) {
+ p.bump();
+ lit = ast::lit_float(p.get_str(s));
+ }
+ case (token::LIT_MACH_INT(?tm, ?i)) {
+ p.bump();
+ lit = ast::lit_mach_int(tm, i);
+ }
+ case (token::LIT_MACH_FLOAT(?tm, ?s)) {
+ p.bump();
+ lit = ast::lit_mach_float(tm, p.get_str(s));
+ }
+ case (token::LIT_CHAR(?c)) {
+ p.bump();
+ lit = ast::lit_char(c);
+ }
+ case (token::LIT_STR(?s)) {
+ p.bump();
+ lit = ast::lit_str(p.get_str(s));
+ }
+ case (?t) {
+ unexpected(p, t);
+ }
}
}
ret rec(node=lit, span=sp);
@@ -643,8 +641,7 @@ fn parse_path(parser p) -> ast::path {
}
fn parse_mutability(parser p) -> ast::mutability {
- if (p.peek() == token::MUTABLE) {
- p.bump();
+ if (eat_word(p, "mutable")) {
if (p.peek() == token::QUES) {
p.bump();
ret ast::maybe_mut;
@@ -672,259 +669,195 @@ fn parse_bottom_expr(parser p) -> @ast::expr {
auto lit = @spanned(lo, hi, ast::lit_nil);
let ast::expr_ ex = ast::expr_lit(lit, p.get_ann());
- alt (p.peek()) {
-
- case (token::IDENT(_)) {
- auto pth = parse_path(p);
- hi = pth.span.hi;
- ex = ast::expr_path(pth, p.get_ann());
- }
-
- case (token::LPAREN) {
- p.bump();
- alt (p.peek()) {
- case (token::RPAREN) {
- hi = p.get_hi_pos();
- p.bump();
- auto lit = @spanned(lo, hi, ast::lit_nil);
- ret @spanned(lo, hi,
- ast::expr_lit(lit, p.get_ann()));
- }
- case (_) { /* fall through */ }
+ if (p.peek() == token::LPAREN) {
+ p.bump();
+ alt (p.peek()) {
+ case (token::RPAREN) {
+ hi = p.get_hi_pos();
+ p.bump();
+ auto lit = @spanned(lo, hi, ast::lit_nil);
+ ret @spanned(lo, hi,
+ ast::expr_lit(lit, p.get_ann()));
}
+ case (_) { /* fall through */ }
+ }
+ auto e = parse_expr(p);
+ hi = p.get_hi_pos();
+ expect(p, token::RPAREN);
+ ret @spanned(lo, hi, e.node);
+ } else if (eat_word(p, "tup")) {
+ fn parse_elt(parser p) -> ast::elt {
+ auto m = parse_mutability(p);
auto e = parse_expr(p);
- hi = p.get_hi_pos();
- expect(p, token::RPAREN);
- ret @spanned(lo, hi, e.node);
- }
-
- case (token::TUP) {
- p.bump();
- fn parse_elt(parser p) -> ast::elt {
- auto m = parse_mutability(p);
- auto e = parse_expr(p);
- ret rec(mut=m, expr=e);
- }
- auto pf = parse_elt;
- auto es =
- parse_seq[ast::elt](token::LPAREN,
- token::RPAREN,
- some(token::COMMA),
- pf, p);
- hi = es.span.hi;
- ex = ast::expr_tup(es.node, p.get_ann());
- }
-
- case (token::VEC) {
- p.bump();
- auto pf = parse_expr;
-
- expect(p, token::LPAREN);
- auto mut = parse_mutability(p);
-
- auto es = parse_seq_to_end[@ast::expr](token::RPAREN,
- some(token::COMMA),
- pf, hi, p);
- ex = ast::expr_vec(es, mut, p.get_ann());
- }
-
- case (token::REC) {
- p.bump();
- expect(p, token::LPAREN);
- auto fields = vec(parse_field(p));
-
- auto more = true;
- auto base = none[@ast::expr];
- while (more) {
- alt (p.peek()) {
- case (token::RPAREN) {
- hi = p.get_hi_pos();
- p.bump();
- more = false;
- }
- case (token::WITH) {
- p.bump();
- base = some[@ast::expr](parse_expr(p));
- hi = p.get_hi_pos();
- expect(p, token::RPAREN);
- more = false;
- }
- case (token::COMMA) {
- p.bump();
- fields += vec(parse_field(p));
- }
- case (?t) {
- unexpected(p, t);
- }
- }
-
- }
-
- ex = ast::expr_rec(fields, base, p.get_ann());
- }
-
- case (token::BIND) {
- p.bump();
- auto e = parse_expr_res(p, RESTRICT_NO_CALL_EXPRS);
- fn parse_expr_opt(parser p) -> option::t[@ast::expr] {
- alt (p.peek()) {
- case (token::UNDERSCORE) {
- p.bump();
- ret none[@ast::expr];
- }
- case (_) {
- ret some[@ast::expr](parse_expr(p));
- }
- }
+ ret rec(mut=m, expr=e);
+ }
+ auto pf = parse_elt;
+ auto es =
+ parse_seq[ast::elt](token::LPAREN,
+ token::RPAREN,
+ some(token::COMMA),
+ pf, p);
+ hi = es.span.hi;
+ ex = ast::expr_tup(es.node, p.get_ann());
+ } else if (eat_word(p, "vec")) {
+ auto pf = parse_expr;
+
+ expect(p, token::LPAREN);
+ auto mut = parse_mutability(p);
+
+ auto es = parse_seq_to_end[@ast::expr](token::RPAREN,
+ some(token::COMMA),
+ pf, hi, p);
+ ex = ast::expr_vec(es, mut, p.get_ann());
+ } else if (eat_word(p, "rec")) {
+ expect(p, token::LPAREN);
+ auto fields = vec(parse_field(p));
+
+ auto more = true;
+ auto base = none[@ast::expr];
+ while (more) {
+ if (p.peek() == token::RPAREN) {
+ hi = p.get_hi_pos();
+ p.bump();
+ more = false;
+ } else if (eat_word(p, "with")) {
+ base = some[@ast::expr](parse_expr(p));
+ hi = p.get_hi_pos();
+ expect(p, token::RPAREN);
+ more = false;
+ } else if (p.peek() == token::COMMA) {
+ p.bump();
+ fields += vec(parse_field(p));
+ } else {
+ unexpected(p, p.peek());
}
- auto pf = parse_expr_opt;
- auto es = parse_seq[option::t[@ast::expr]](token::LPAREN,
- token::RPAREN,
- some(token::COMMA),
- pf, p);
- hi = es.span.hi;
- ex = ast::expr_bind(e, es.node, p.get_ann());
}
- case (token::POUND) {
- p.bump();
- auto pth = parse_path(p);
- auto pf = parse_expr;
- auto es = parse_seq[@ast::expr](token::LPAREN,
- token::RPAREN,
- some(token::COMMA),
- pf, p);
- hi = es.span.hi;
- ex = expand_syntax_ext(p, es.span, pth, es.node,
- none[str]);
- }
-
- case (token::FAIL) {
- p.bump();
- ex = ast::expr_fail(p.get_ann());
- }
-
- case (token::LOG) {
- p.bump();
- auto e = parse_expr(p);
- auto hi = e.span.hi;
- ex = ast::expr_log(1, e, p.get_ann());
- }
-
- case (token::LOG_ERR) {
- p.bump();
- auto e = parse_expr(p);
- auto hi = e.span.hi;
- ex = ast::expr_log(0, e, p.get_ann());
- }
-
- case (token::ASSERT) {
- p.bump();
- auto e = parse_expr(p);
- auto hi = e.span.hi;
- ex = ast::expr_assert(e, p.get_ann());
- }
-
- case (token::CHECK) {
- p.bump();
- /* Should be a predicate (pure boolean function) applied to
- arguments that are all either slot variables or literals.
- but the typechecker enforces that. */
- auto e = parse_expr(p);
- auto hi = e.span.hi;
- ex = ast::expr_check(e, p.get_ann());
- }
-
- case (token::RET) {
- p.bump();
+ ex = ast::expr_rec(fields, base, p.get_ann());
+ } 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] {
alt (p.peek()) {
- case (token::SEMI) {
- ex = ast::expr_ret(none[@ast::expr], p.get_ann());
+ case (token::UNDERSCORE) {
+ p.bump();
+ ret none[@ast::expr];
}
case (_) {
- auto e = parse_expr(p);
- hi = e.span.hi;
- ex = ast::expr_ret(some[@ast::expr](e), p.get_ann());
+ ret some[@ast::expr](parse_expr(p));
}
}
}
- case (token::BREAK) {
- p.bump();
- ex = ast::expr_break(p.get_ann());
- }
-
- case (token::CONT) {
- p.bump();
- ex = ast::expr_cont(p.get_ann());
- }
-
- case (token::PUT) {
- p.bump();
- alt (p.peek()) {
- case (token::SEMI) {
- ex = ast::expr_put(none[@ast::expr], p.get_ann());
- }
- case (_) {
- auto e = parse_expr(p);
- hi = e.span.hi;
- ex = ast::expr_put(some[@ast::expr](e), p.get_ann());
- }
+ auto pf = parse_expr_opt;
+ auto es = parse_seq[option::t[@ast::expr]](token::LPAREN,
+ token::RPAREN,
+ some(token::COMMA),
+ pf, p);
+ hi = es.span.hi;
+ ex = ast::expr_bind(e, es.node, p.get_ann());
+ } else if (p.peek() == token::POUND) {
+ p.bump();
+ auto pth = parse_path(p);
+ auto pf = parse_expr;
+ auto es = parse_seq[@ast::expr](token::LPAREN,
+ token::RPAREN,
+ some(token::COMMA),
+ pf, p);
+ hi = es.span.hi;
+ ex = expand_syntax_ext(p, es.span, pth, es.node,
+ none[str]);
+ } else if (eat_word(p, "fail")) {
+ p.bump();
+ ex = ast::expr_fail(p.get_ann());
+ } else if (eat_word(p, "log")) {
+ auto e = parse_expr(p);
+ auto hi = e.span.hi;
+ ex = ast::expr_log(1, e, p.get_ann());
+ } else if (eat_word(p, "log_err")) {
+ auto e = parse_expr(p);
+ auto hi = e.span.hi;
+ ex = ast::expr_log(0, e, p.get_ann());
+ } else if (eat_word(p, "assert")) {
+ auto e = parse_expr(p);
+ auto hi = e.span.hi;
+ ex = ast::expr_assert(e, p.get_ann());
+ } else if (eat_word(p, "check")) {
+ /* Should be a predicate (pure boolean function) applied to
+ arguments that are all either slot variables or literals.
+ but the typechecker enforces that. */
+ auto e = parse_expr(p);
+ auto hi = e.span.hi;
+ ex = ast::expr_check(e, p.get_ann());
+ } else if (eat_word(p, "ret")) {
+ alt (p.peek()) {
+ case (token::SEMI) {
+ ex = ast::expr_ret(none[@ast::expr], p.get_ann());
+ }
+ case (_) {
+ auto e = parse_expr(p);
+ hi = e.span.hi;
+ ex = ast::expr_ret(some[@ast::expr](e), p.get_ann());
}
}
-
- case (token::BE) {
- p.bump();
- auto e = parse_expr(p);
- // FIXME: Is this the right place for this check?
- if /*check*/ (ast::is_call_expr(e)) {
- hi = e.span.hi;
- ex = ast::expr_be(e, p.get_ann());
+ } else if (eat_word(p, "break")) {
+ ex = ast::expr_break(p.get_ann());
+ } else if (eat_word(p, "cont")) {
+ ex = ast::expr_cont(p.get_ann());
+ } else if (eat_word(p, "put")) {
+ alt (p.peek()) {
+ case (token::SEMI) {
+ ex = ast::expr_put(none[@ast::expr], p.get_ann());
}
- else {
- p.err("Non-call expression in tail call");
+ case (_) {
+ auto e = parse_expr(p);
+ hi = e.span.hi;
+ ex = ast::expr_put(some[@ast::expr](e), p.get_ann());
}
}
-
- case (token::PORT) {
- p.bump();
- expect(p, token::LPAREN);
- expect(p, token::RPAREN);
- hi = p.get_hi_pos();
- ex = ast::expr_port(p.get_ann());
- }
-
- case (token::CHAN) {
- p.bump();
- expect(p, token::LPAREN);
- auto e = parse_expr(p);
+ } else if (eat_word(p, "be")) {
+ auto e = parse_expr(p);
+ // FIXME: Is this the right place for this check?
+ if /*check*/ (ast::is_call_expr(e)) {
hi = e.span.hi;
- expect(p, token::RPAREN);
- ex = ast::expr_chan(e, p.get_ann());
- }
-
- case (token::SELF) {
- log "parsing a self-call...";
-
- p.bump();
- expect(p, token::DOT);
- // The rest is a call expression.
- let @ast::expr f = parse_self_method(p);
- auto pf = parse_expr;
- auto es = parse_seq[@ast::expr](token::LPAREN,
- token::RPAREN,
- some(token::COMMA),
- pf, p);
- hi = es.span.hi;
- ex = ast::expr_call(f, es.node, p.get_ann());
- }
-
- case (_) {
- auto lit = parse_lit(p);
- hi = lit.span.hi;
- ex = ast::expr_lit(@lit, p.get_ann());
- }
+ ex = ast::expr_be(e, p.get_ann());
+ }
+ else {
+ p.err("Non-call expression in tail call");
+ }
+ } else if (eat_word(p, "port")) {
+ expect(p, token::LPAREN);
+ expect(p, token::RPAREN);
+ hi = p.get_hi_pos();
+ ex = ast::expr_port(p.get_ann());
+ } else if (eat_word(p, "chan")) {
+ expect(p, token::LPAREN);
+ auto e = parse_expr(p);
+ hi = e.span.hi;
+ expect(p, token::RPAREN);
+ ex = ast::expr_chan(e, p.get_ann());
+ } else if (eat_word(p, "self")) {
+ log "parsing a self-call...";
+
+ expect(p, token::DOT);
+ // The rest is a call expression.
+ let @ast::expr f = parse_self_method(p);
+ auto pf = parse_expr;
+ auto es = parse_seq[@ast::expr](token::LPAREN,
+ token::RPAREN,
+ some(token::COMMA),
+ pf, p);
+ hi = es.span.hi;
+ ex = ast::expr_call(f, es.node, p.get_ann());
+ } else if (is_ident(p.peek()) && !is_word(p, "true") &&
+ !is_word(p, "false")) {
+ auto pth = parse_path(p);
+ hi = pth.span.hi;
+ ex = ast::expr_path(pth, p.get_ann());
+ } else {
+ auto lit = parse_lit(p);
+ hi = lit.span.hi;
+ ex = ast::expr_lit(@lit, p.get_ann());
}
ret @spanned(lo, hi, ex);
@@ -1031,8 +964,7 @@ fn parse_dot_or_call_expr(parser p) -> @ast::expr {
fn parse_prefix_expr(parser p) -> @ast::expr {
- if (p.peek() == token::MUTABLE) {
- p.bump();
+ if (eat_word(p, "mutable")) {
p.get_session().span_warn(p.get_span(),
"ignoring deprecated 'mutable' prefix operator");
}
@@ -1113,9 +1045,7 @@ fn prec_table() -> vec[op_spec] {
rec(tok=token::BINOP(token::AND), op=ast::bitand, prec=8),
rec(tok=token::BINOP(token::CARET), op=ast::bitxor, prec=6),
rec(tok=token::BINOP(token::OR), op=ast::bitor, prec=6),
- // ast::mul is a bogus placeholder here, AS is special
- // cased in parse_more_binops
- rec(tok=token::AS, op=ast::mul, prec=5),
+ // 'as' sits between here with 5
rec(tok=token::LT, op=ast::lt, prec=4),
rec(tok=token::LE, op=ast::le, prec=4),
rec(tok=token::GE, op=ast::ge, prec=4),
@@ -1130,35 +1060,28 @@ fn parse_binops(parser p) -> @ast::expr {
ret parse_more_binops(p, parse_prefix_expr(p), 0);
}
+const int as_prec = 5;
+
fn parse_more_binops(parser p, @ast::expr lhs, int min_prec)
-> @ast::expr {
- // Magic nonsense to work around rustboot bug
- fn op_eq(token::token a, token::token b) -> bool {
- if (a == b) {ret true;}
- else {ret false;}
- }
auto peeked = p.peek();
for (op_spec cur in p.get_prec_table()) {
- if (cur.prec > min_prec && op_eq(cur.tok, peeked)) {
+ if (cur.prec > min_prec && cur.tok == peeked) {
p.bump();
- alt (cur.tok) {
- case (token::AS) {
- auto rhs = parse_ty(p);
- auto _as = ast::expr_cast(lhs, rhs, p.get_ann());
- auto span = @spanned(lhs.span.lo, rhs.span.hi, _as);
- ret parse_more_binops(p, span, min_prec);
- }
- case (_) {
- auto rhs = parse_more_binops(p, parse_prefix_expr(p),
- cur.prec);
- auto bin = ast::expr_binary(cur.op, lhs, rhs,
- p.get_ann());
- auto span = @spanned(lhs.span.lo, rhs.span.hi, bin);
- ret parse_more_binops(p, span, min_prec);
- }
- }
+ auto rhs = parse_more_binops(p, parse_prefix_expr(p),
+ cur.prec);
+ auto bin = ast::expr_binary(cur.op, lhs, rhs,
+ p.get_ann());
+ auto span = @spanned(lhs.span.lo, rhs.span.hi, bin);
+ ret parse_more_binops(p, span, min_prec);
}
}
+ if (as_prec > min_prec && eat_word(p, "as")) {
+ auto rhs = parse_ty(p);
+ auto _as = ast::expr_cast(lhs, rhs, p.get_ann());
+ auto span = @spanned(lhs.span.lo, rhs.span.hi, _as);
+ ret parse_more_binops(p, span, min_prec);
+ }
ret lhs;
}
@@ -1210,45 +1133,37 @@ fn parse_assign_expr(parser p) -> @ast::expr {
}
fn parse_if_expr(parser p) -> @ast::expr {
- auto lo = p.get_lo_pos();
+ auto lo = p.get_last_lo_pos();
- expect(p, token::IF);
expect(p, token::LPAREN);
auto cond = parse_expr(p);
expect(p, token::RPAREN);
auto thn = parse_block(p);
let option::t[@ast::expr] els = none[@ast::expr];
auto hi = thn.span.hi;
- alt (p.peek()) {
- case (token::ELSE) {
- auto elexpr = parse_else_expr(p);
- els = some(elexpr);
- hi = elexpr.span.hi;
- }
- case (_) { /* fall through */ }
+ if (eat_word(p, "else")) {
+ auto elexpr = parse_else_expr(p);
+ els = some(elexpr);
+ hi = elexpr.span.hi;
}
ret @spanned(lo, hi, ast::expr_if(cond, thn, els, p.get_ann()));
}
fn parse_else_expr(parser p) -> @ast::expr {
- expect(p, token::ELSE);
- alt (p.peek()) {
- case (token::IF) {
- ret parse_if_expr(p);
- }
- case (_) {
- auto blk = parse_block(p);
- ret @spanned(blk.span.lo, blk.span.hi,
- ast::expr_block(blk, p.get_ann()));
- }
+ if (eat_word(p, "if")) {
+ ret parse_if_expr(p);
+ } else {
+ auto blk = parse_block(p);
+ ret @spanned(blk.span.lo, blk.span.hi,
+ ast::expr_block(blk, p.get_ann()));
}
}
fn parse_head_local(parser p) -> @ast::decl {
auto lo = p.get_lo_pos();
let @ast::local local;
- if (p.peek() == token::AUTO) {
+ if (is_word(p, "auto")) {
local = parse_auto_local(p);
} else {
local = parse_typed_local(p);
@@ -1259,19 +1174,14 @@ fn parse_head_local(parser p) -> @ast::decl {
fn parse_for_expr(parser p) -> @ast::expr {
- auto lo = p.get_lo_pos();
- auto is_each = false;
+ auto lo = p.get_last_lo_pos();
- expect(p, token::FOR);
- if (p.peek() == token::EACH) {
- is_each = true;
- p.bump();
- }
+ auto is_each = eat_word(p, "each");
expect (p, token::LPAREN);
auto decl = parse_head_local(p);
- expect(p, token::IN);
+ expect_word(p, "in");
auto seq = parse_expr(p);
expect(p, token::RPAREN);
@@ -1288,10 +1198,8 @@ fn parse_for_expr(parser p) -> @ast::expr {
fn parse_while_expr(parser p) -> @ast::expr {
- auto lo = p.get_lo_pos();
-
- expect(p, token::WHILE);
- expect (p, token::LPAREN);
+ auto lo = p.get_last_lo_pos();
+ expect(p, token::LPAREN);
auto cond = parse_expr(p);
expect(p, token::RPAREN);
auto body = parse_block(p);
@@ -1300,11 +1208,9 @@ fn parse_while_expr(parser p) -> @ast::expr {
}
fn parse_do_while_expr(parser p) -> @ast::expr {
- auto lo = p.get_lo_pos();
-
- expect(p, token::DO);
+ auto lo = p.get_last_lo_pos();
auto body = parse_block(p);
- expect(p, token::WHILE);
+ expect_word(p, "while");
expect (p, token::LPAREN);
auto cond = parse_expr(p);
expect(p, token::RPAREN);
@@ -1313,8 +1219,7 @@ fn parse_do_while_expr(parser p) -> @ast::expr {
}
fn parse_alt_expr(parser p) -> @ast::expr {
- auto lo = p.get_lo_pos();
- expect(p, token::ALT);
+ auto lo = p.get_last_lo_pos();
expect(p, token::LPAREN);
auto discriminant = parse_expr(p);
expect(p, token::RPAREN);
@@ -1322,36 +1227,17 @@ fn parse_alt_expr(parser p) -> @ast::expr {
let vec[ast::arm] arms = vec();
while (p.peek() != token::RBRACE) {
- alt (p.peek()) {
- case (token::CASE) {
- p.bump();
- expect(p, token::LPAREN);
- auto pat = parse_pat(p);
- expect(p, token::RPAREN);
- auto block = parse_block(p);
- arms += vec(rec(pat=pat, block=block));
- }
-
- // FIXME: this is a vestigial form left over from
- // rustboot, we're keeping it here for source-compat
- // for the time being but it should be flushed out
- // once we've bootstrapped. When we see 'else {' here,
- // we pretend we saw 'case (_) {'. It has the same
- // meaning, and only exists due to the cexp/pexp split
- // in rustboot, which we're not maintaining.
-
- case (token::ELSE) {
- p.bump();
- auto hi = p.get_hi_pos();
- auto pat = @spanned(lo, hi, ast::pat_wild(p.get_ann()));
- auto block = parse_block(p);
- arms += vec(rec(pat=pat, block=block));
- }
- case (token::RBRACE) { /* empty */ }
- case (?tok) {
- p.err("expected 'case' or '}' when parsing 'alt' statement " +
- "but found " + token::to_str(p.get_reader(), tok));
- }
+ if (eat_word(p, "case")) {
+ expect(p, token::LPAREN);
+ auto pat = parse_pat(p);
+ expect(p, token::RPAREN);
+ auto block = parse_block(p);
+ arms += vec(rec(pat=pat, block=block));
+ } else if (p.peek() == token::RBRACE) {
+ /* empty */
+ } else {
+ p.err("expected 'case' or '}' when parsing 'alt' statement " +
+ "but found " + token::to_str(p.get_reader(), p.peek()));
}
}
auto hi = p.get_hi_pos();
@@ -1362,9 +1248,7 @@ fn parse_alt_expr(parser p) -> @ast::expr {
}
fn parse_spawn_expr(parser p) -> @ast::expr {
- auto lo = p.get_lo_pos();
- expect(p, token::SPAWN);
-
+ auto lo = p.get_last_lo_pos();
// FIXME: Parse domain and name
// FIXME: why no full expr?
auto fn_expr = parse_bottom_expr(p);
@@ -1395,34 +1279,24 @@ fn parse_expr_res(parser p, restriction r) -> @ast::expr {
}
fn parse_expr_inner(parser p) -> @ast::expr {
- alt (p.peek()) {
- case (token::LBRACE) {
- auto blk = parse_block(p);
- ret @spanned(blk.span.lo, blk.span.hi,
- ast::expr_block(blk, p.get_ann()));
- }
- case (token::IF) {
- ret parse_if_expr(p);
- }
- case (token::FOR) {
- ret parse_for_expr(p);
- }
- case (token::WHILE) {
- ret parse_while_expr(p);
- }
- case (token::DO) {
- ret parse_do_while_expr(p);
- }
- case (token::ALT) {
- ret parse_alt_expr(p);
- }
- case (token::SPAWN) {
- ret parse_spawn_expr(p);
- }
- case (_) {
- ret parse_assign_expr(p);
- }
-
+ if (p.peek() == token::LBRACE) {
+ auto blk = parse_block(p);
+ ret @spanned(blk.span.lo, blk.span.hi,
+ ast::expr_block(blk, p.get_ann()));
+ } else if (eat_word(p, "if")) {
+ ret parse_if_expr(p);
+ } else if (eat_word(p, "for")) {
+ ret parse_for_expr(p);
+ } else if (eat_word(p, "while")) {
+ ret parse_while_expr(p);
+ } else if (eat_word(p, "do")) {
+ ret parse_do_while_expr(p);
+ } else if (eat_word(p, "alt")) {
+ ret parse_alt_expr(p);
+ } else if (eat_word(p, "spawn")) {
+ ret parse_spawn_expr(p);
+ } else {
+ ret parse_assign_expr(p);
}
}
@@ -1470,29 +1344,30 @@ fn parse_pat(parser p) -> @ast::pat {
}
}
}
- case (token::IDENT(_)) {
- auto tag_path = parse_path(p);
- hi = tag_path.span.hi;
+ case (?tok) {
+ if (!is_ident(tok) || is_word(p, "true") || is_word(p, "false")) {
+ auto lit = parse_lit(p);
+ hi = lit.span.hi;
+ pat = ast::pat_lit(@lit, p.get_ann());
+ } else {
+ auto tag_path = parse_path(p);
+ hi = tag_path.span.hi;
- let vec[@ast::pat] args;
- alt (p.peek()) {
- case (token::LPAREN) {
- auto f = parse_pat;
- auto a = parse_seq[@ast::pat](token::LPAREN,
- token::RPAREN,
- some(token::COMMA), f, p);
- args = a.node;
- hi = a.span.hi;
+ let vec[@ast::pat] args;
+ alt (p.peek()) {
+ case (token::LPAREN) {
+ auto f = parse_pat;
+ auto a = parse_seq(token::LPAREN,
+ token::RPAREN,
+ some(token::COMMA), f, p);
+ args = a.node;
+ hi = a.span.hi;
+ }
+ case (_) { args = vec(); }
}
- case (_) { args = vec(); }
- }
- pat = ast::pat_tag(tag_path, args, p.get_ann());
- }
- case (_) {
- auto lit = parse_lit(p);
- hi = lit.span.hi;
- pat = ast::pat_lit(@lit, p.get_ann());
+ pat = ast::pat_tag(tag_path, args, p.get_ann());
+ }
}
}
@@ -1521,15 +1396,13 @@ fn parse_auto_local(parser p) -> @ast::local {
}
fn parse_let(parser p) -> @ast::decl {
- auto lo = p.get_lo_pos();
- expect(p, token::LET);
+ auto lo = p.get_last_lo_pos();
auto local = parse_typed_local(p);
ret @spanned(lo, p.get_hi_pos(), ast::decl_local(local));
}
fn parse_auto(parser p) -> @ast::decl {
- auto lo = p.get_lo_pos();
- expect(p, token::AUTO);
+ auto lo = p.get_last_lo_pos();
auto local = parse_auto_local(p);
ret @spanned(lo, p.get_hi_pos(), ast::decl_local(local));
}
@@ -1550,35 +1423,28 @@ fn parse_crate_stmt(parser p) -> @ast::stmt {
fn parse_source_stmt(parser p) -> @ast::stmt {
auto lo = p.get_lo_pos();
- alt (p.peek()) {
-
- case (token::LET) {
- auto decl = parse_let(p);
- auto hi = p.get_span();
- ret @spanned
- (lo, decl.span.hi, ast::stmt_decl(decl, p.get_ann()));
- }
+ if (eat_word(p, "let")) {
+ auto decl = parse_let(p);
+ auto hi = p.get_span();
+ ret @spanned
+ (lo, decl.span.hi, ast::stmt_decl(decl, p.get_ann()));
+ } else if (eat_word(p, "auto")) {
+ auto decl = parse_auto(p);
+ auto hi = p.get_span();
+ ret @spanned(lo, decl.span.hi, ast::stmt_decl(decl, p.get_ann()));
+ } else {
+ if (peeking_at_item(p)) {
+ // Might be a local item decl.
+ auto i = parse_item(p);
+ auto hi = i.span.hi;
+ auto decl = @spanned(lo, hi, ast::decl_item(i));
+ ret @spanned(lo, hi, ast::stmt_decl(decl, p.get_ann()));
- case (token::AUTO) {
- auto decl = parse_auto(p);
+ } else {
+ // Remainder are line-expr stmts.
+ auto e = parse_expr(p);
auto hi = p.get_span();
- ret @spanned(lo, decl.span.hi, ast::stmt_decl(decl, p.get_ann()));
- }
-
- case (_) {
- if (peeking_at_item(p)) {
- // Might be a local item decl.
- auto i = parse_item(p);
- auto hi = i.span.hi;
- auto decl = @spanned(lo, hi, ast::decl_item(i));
- ret @spanned(lo, hi, ast::stmt_decl(decl, p.get_ann()));
-
- } else {
- // Remainder are line-expr stmts.
- auto e = parse_expr(p);
- auto hi = p.get_span();
- ret @spanned(lo, e.span.hi, ast::stmt_expr(e, p.get_ann()));
- }
+ ret @spanned(lo, e.span.hi, ast::stmt_expr(e, p.get_ann()));
}
}
p.err("expected statement");
@@ -1761,9 +1627,9 @@ fn parse_fn_header(parser p)
ret tup(id, ty_params);
}
-fn parse_item_fn_or_iter(parser p, ast::purity purity) -> @ast::item {
- auto lo = p.get_lo_pos();
- auto proto = parse_proto(p);
+fn parse_item_fn_or_iter(parser p, ast::purity purity, ast::proto proto)
+ -> @ast::item {
+ auto lo = p.get_last_lo_pos();
auto t = parse_fn_header(p);
auto f = parse_fn(p, proto, purity);
auto item = ast::item_fn(t._0, f, t._1,
@@ -1790,8 +1656,7 @@ fn parse_method(parser p) -> @ast::method {
}
fn parse_dtor(parser p) -> @ast::method {
- auto lo = p.get_lo_pos();
- expect(p, token::DROP);
+ auto lo = p.get_last_lo_pos();
let ast::block b = parse_block(p);
let vec[ast::arg] inputs = vec();
let @ast::ty output = @spanned(lo, lo, ast::ty_nil);
@@ -1809,8 +1674,7 @@ fn parse_dtor(parser p) -> @ast::method {
}
fn parse_item_obj(parser p, ast::layer lyr) -> @ast::item {
- auto lo = p.get_lo_pos();
- expect(p, token::OBJ);
+ auto lo = p.get_last_lo_pos();
auto ident = parse_ident(p);
auto ty_params = parse_ty_params(p);
auto pf = parse_obj_field;
@@ -1826,14 +1690,11 @@ fn parse_item_obj(parser p, ast::layer lyr) -> @ast::item {
expect(p, token::LBRACE);
while (p.peek() != token::RBRACE) {
- alt (p.peek()) {
- case (token::DROP) {
- dtor = some[@ast::method](parse_dtor(p));
- }
- case (_) {
- _vec::push[@ast::method](meths,
- parse_method(p));
- }
+ if (eat_word(p, "drop")) {
+ dtor = some[@ast::method](parse_dtor(p));
+ } else {
+ _vec::push[@ast::method](meths,
+ parse_method(p));
}
}
auto hi = p.get_hi_pos();
@@ -1859,8 +1720,7 @@ fn parse_mod_items(parser p, token::token term) -> ast::_mod {
}
fn parse_item_const(parser p) -> @ast::item {
- auto lo = p.get_lo_pos();
- expect(p, token::CONST);
+ auto lo = p.get_last_lo_pos();
auto ty = parse_ty(p);
auto id = parse_ident(p);
expect(p, token::EQ);
@@ -1872,8 +1732,7 @@ fn parse_item_const(parser p) -> @ast::item {
}
fn parse_item_mod(parser p) -> @ast::item {
- auto lo = p.get_lo_pos();
- expect(p, token::MOD);
+ auto lo = p.get_last_lo_pos();
auto id = parse_ident(p);
expect(p, token::LBRACE);
auto m = parse_mod_items(p, token::RBRACE);
@@ -1892,8 +1751,7 @@ fn parse_item_native_type(parser p) -> @ast::native_item {
}
fn parse_item_native_fn(parser p) -> @ast::native_item {
- auto lo = p.get_lo_pos();
- expect(p, token::FN);
+ auto lo = p.get_last_lo_pos();
auto t = parse_fn_header(p);
auto decl = parse_fn_decl(p, ast::impure_fn);
auto link_name = none[str];
@@ -1911,17 +1769,13 @@ fn parse_item_native_fn(parser p) -> @ast::native_item {
fn parse_native_item(parser p) -> @ast::native_item {
let ast::layer lyr = parse_layer(p);
- alt (p.peek()) {
- case (token::TYPE) {
- ret parse_item_native_type(p);
- }
- case (token::FN) {
- ret parse_item_native_fn(p);
- }
- case (?t) {
- unexpected(p, t);
- fail;
- }
+ if (eat_word(p, "type")) {
+ ret parse_item_native_type(p);
+ } else if (eat_word(p, "fn")) {
+ ret parse_item_native_fn(p);
+ } else {
+ unexpected(p, p.peek());
+ fail;
}
}
@@ -1955,10 +1809,9 @@ fn default_native_name(session::session sess, str id) -> str {
}
fn parse_item_native_mod(parser p) -> @ast::item {
- auto lo = p.get_lo_pos();
- expect(p, token::NATIVE);
+ auto lo = p.get_last_lo_pos();
auto abi = ast::native_abi_cdecl;
- if (p.peek() != token::MOD) {
+ if (!is_word(p, "mod")) {
auto t = parse_str_lit_or_env_ident(p);
if (_str::eq(t, "cdecl")) {
} else if (_str::eq(t, "rust")) {
@@ -1972,7 +1825,7 @@ fn parse_item_native_mod(parser p) -> @ast::item {
fail;
}
}
- expect(p, token::MOD);
+ expect_word(p, "mod");
auto id = parse_ident(p);
auto native_name;
if (p.peek() == token::EQ) {
@@ -1990,8 +1843,7 @@ fn parse_item_native_mod(parser p) -> @ast::item {
}
fn parse_type_decl(parser p) -> tup(uint, ast::ident) {
- auto lo = p.get_lo_pos();
- expect(p, token::TYPE);
+ auto lo = p.get_last_lo_pos();
auto id = parse_ident(p);
ret tup(lo, id);
}
@@ -2009,8 +1861,7 @@ fn parse_item_type(parser p) -> @ast::item {
}
fn parse_item_tag(parser p) -> @ast::item {
- auto lo = p.get_lo_pos();
- expect(p, token::TAG);
+ auto lo = p.get_last_lo_pos();
auto id = parse_ident(p);
auto ty_params = parse_ty_params(p);
@@ -2063,97 +1914,75 @@ fn parse_item_tag(parser p) -> @ast::item {
fn parse_layer(parser p) -> ast::layer {
- alt (p.peek()) {
- case (token::STATE) {
- p.bump();
- ret ast::layer_state;
- }
- case (token::GC) {
- p.bump();
- ret ast::layer_gc;
- }
- case (_) {
- ret ast::layer_value;
- }
+ if (eat_word(p, "state")) {
+ ret ast::layer_state;
+ } else if (eat_word(p, "gc")) {
+ ret ast::layer_gc;
+ } else {
+ ret ast::layer_value;
}
fail;
}
fn parse_auth(parser p) -> ast::_auth {
- alt (p.peek()) {
- case (token::UNSAFE) {
- p.bump();
- ret ast::auth_unsafe;
- }
- case (?t) {
- unexpected(p, t);
- }
+ if (eat_word(p, "unsafe")) {
+ ret ast::auth_unsafe;
+ } else {
+ unexpected(p, p.peek());
}
fail;
}
fn peeking_at_item(parser p) -> bool {
alt (p.peek()) {
- case (token::STATE) { ret true; }
- case (token::GC) { ret true; }
- case (token::CONST) { ret true; }
- case (token::FN) { ret true; }
- case (token::PRED) { ret true; }
- case (token::ITER) { ret true; }
- case (token::MOD) { ret true; }
- case (token::TYPE) { ret true; }
- case (token::TAG) { ret true; }
- case (token::OBJ) { ret true; }
+ case (token::IDENT(?sid)) {
+ auto st = p.get_str(sid);
+ ret _str::eq(st, "state") ||
+ _str::eq(st, "gc") ||
+ _str::eq(st, "const") ||
+ _str::eq(st, "fn") ||
+ _str::eq(st, "pred") ||
+ _str::eq(st, "iter") ||
+ _str::eq(st, "mod") ||
+ _str::eq(st, "type") ||
+ _str::eq(st, "tag") ||
+ _str::eq(st, "obj");
+ }
case (_) { ret false; }
}
- ret false;
}
fn parse_item(parser p) -> @ast::item {
let ast::layer lyr = parse_layer(p);
- alt (p.peek()) {
- case (token::CONST) {
- assert (lyr == ast::layer_value);
- ret parse_item_const(p);
- }
-
- case (token::FN) {
- assert (lyr == ast::layer_value);
- ret parse_item_fn_or_iter(p, ast::impure_fn);
- }
-
- case (token::PRED) {
- assert (lyr == ast::layer_value);
- ret parse_item_fn_or_iter(p, ast::pure_fn);
- }
-
- case (token::ITER) {
- assert (lyr == ast::layer_value);
- ret parse_item_fn_or_iter(p, ast::impure_fn);
- }
- case (token::MOD) {
- assert (lyr == ast::layer_value);
- ret parse_item_mod(p);
- }
- case (token::NATIVE) {
- assert (lyr == ast::layer_value);
- ret parse_item_native_mod(p);
- }
- case (token::TYPE) {
- ret parse_item_type(p);
- }
- case (token::TAG) {
- ret parse_item_tag(p);
- }
- case (token::OBJ) {
- ret parse_item_obj(p, lyr);
- }
- case (?t) {
- p.err("expected item but found " +
- token::to_str(p.get_reader(), t));
- }
+ if (eat_word(p, "const")) {
+ assert (lyr == ast::layer_value);
+ ret parse_item_const(p);
+ } else if (eat_word(p, "fn")) {
+ assert (lyr == ast::layer_value);
+ ret parse_item_fn_or_iter(p, ast::impure_fn, ast::proto_fn);
+ } else if (eat_word(p, "pred")) {
+ assert (lyr == ast::layer_value);
+ ret parse_item_fn_or_iter(p, ast::pure_fn, ast::proto_fn);
+ } else if (eat_word(p, "iter")) {
+ assert (lyr == ast::layer_value);
+ ret parse_item_fn_or_iter(p, ast::impure_fn, ast::proto_iter);
+ } else if (eat_word(p, "mod")) {
+ assert (lyr == ast::layer_value);
+ ret parse_item_mod(p);
+ } else if (eat_word(p, "native")) {
+ assert (lyr == ast::layer_value);
+ ret parse_item_native_mod(p);
+ } else if (eat_word(p, "type")) {
+ ret parse_item_type(p);
+ } else if (eat_word(p, "tag")) {
+ ret parse_item_tag(p);
+ } else if (eat_word(p, "obj")) {
+ ret parse_item_obj(p, lyr);
+ } else {
+ p.err("expected item but found " +
+ token::to_str(p.get_reader(), p.peek()));
}
fail;
}
@@ -2195,8 +2024,7 @@ fn parse_optional_meta(parser p) -> vec[@ast::meta_item] {
}
fn parse_use(parser p) -> @ast::view_item {
- auto lo = p.get_lo_pos();
- expect(p, token::USE);
+ auto lo = p.get_last_lo_pos();
auto ident = parse_ident(p);
auto metadata = parse_optional_meta(p);
auto hi = p.get_hi_pos();
@@ -2248,7 +2076,6 @@ fn parse_full_import_name(parser p, ast::ident def_ident)
}
fn parse_import(parser p) -> @ast::view_item {
- expect(p, token::IMPORT);
alt (p.peek()) {
case (token::IDENT(?i)) {
p.bump();
@@ -2271,8 +2098,7 @@ fn parse_import(parser p) -> @ast::view_item {
}
fn parse_export(parser p) -> @ast::view_item {
- auto lo = p.get_lo_pos();
- expect(p, token::EXPORT);
+ auto lo = p.get_last_lo_pos();
auto id = parse_ident(p);
auto hi = p.get_hi_pos();
expect(p, token::SEMI);
@@ -2280,32 +2106,32 @@ fn parse_export(parser p) -> @ast::view_item {
}
fn parse_view_item(parser p) -> @ast::view_item {
- alt (p.peek()) {
- case (token::USE) {
- ret parse_use(p);
- }
- case (token::IMPORT) {
- ret parse_import(p);
- }
- case (token::EXPORT) {
- ret parse_export(p);
- }
+ if (eat_word(p, "use")) {
+ ret parse_use(p);
+ } else if (eat_word(p, "import")) {
+ ret parse_import(p);
+ } else if (eat_word(p, "export")) {
+ ret parse_export(p);
+ } else {
+ fail;
}
}
-fn is_view_item(token::token t) -> bool {
- alt (t) {
- case (token::USE) { ret true; }
- case (token::IMPORT) { ret true; }
- case (token::EXPORT) { ret true; }
- case (_) {}
+fn is_view_item(&parser p) -> bool {
+ alt (p.peek()) {
+ case (token::IDENT(?sid)) {
+ auto st = p.get_str(sid);
+ ret _str::eq(st, "use") || _str::eq(st, "import") ||
+ _str::eq(st, "export");
+ }
+ case (_) { ret false; }
}
ret false;
}
fn parse_view(parser p) -> vec[@ast::view_item] {
let vec[@ast::view_item] items = vec();
- while (is_view_item(p.peek())) {
+ while (is_view_item(p)) {
items += vec(parse_view_item(p));
}
ret items;
@@ -2313,7 +2139,7 @@ fn parse_view(parser p) -> vec[@ast::view_item] {
fn parse_native_view(parser p) -> vec[@ast::view_item] {
let vec[@ast::view_item] items = vec();
- while (is_view_item(p.peek())) {
+ while (is_view_item(p)) {
items += vec(parse_view_item(p));
}
ret items;
@@ -2337,99 +2163,79 @@ fn parse_crate_from_source_file(parser p) -> @ast::crate {
fn parse_crate_directive(parser p) -> ast::crate_directive
{
auto lo = p.get_lo_pos();
- alt (p.peek()) {
- case (token::AUTH) {
- p.bump();
- auto n = parse_path(p);
- expect(p, token::EQ);
- auto a = parse_auth(p);
- auto hi = p.get_hi_pos();
- expect(p, token::SEMI);
- ret spanned(lo, hi, ast::cdir_auth(n, a));
- }
-
- case (token::META) {
- p.bump();
- auto mis = parse_meta(p);
- auto hi = p.get_hi_pos();
- expect(p, token::SEMI);
- ret spanned(lo, hi, ast::cdir_meta(mis));
- }
-
- case (token::MOD) {
- p.bump();
- auto id = parse_ident(p);
- auto file_opt = none[filename];
- alt (p.peek()) {
- case (token::EQ) {
- p.bump();
- // FIXME: turn this into parse+eval expr
- file_opt = some[filename](parse_str_lit_or_env_ident(p));
- }
- case (_) {}
+ if (eat_word(p, "auth")) {
+ auto n = parse_path(p);
+ expect(p, token::EQ);
+ auto a = parse_auth(p);
+ auto hi = p.get_hi_pos();
+ expect(p, token::SEMI);
+ ret spanned(lo, hi, ast::cdir_auth(n, a));
+ } else if (eat_word(p, "meta")) {
+ auto mis = parse_meta(p);
+ auto hi = p.get_hi_pos();
+ expect(p, token::SEMI);
+ ret spanned(lo, hi, ast::cdir_meta(mis));
+ } else if (eat_word(p, "mod")) {
+ auto id = parse_ident(p);
+ auto file_opt = none[filename];
+ alt (p.peek()) {
+ case (token::EQ) {
+ p.bump();
+ // FIXME: turn this into parse+eval expr
+ file_opt = some[filename](parse_str_lit_or_env_ident(p));
}
+ case (_) {}
+ }
- alt (p.peek()) {
-
- // mod x = "foo.rs";
-
- case (token::SEMI) {
- auto hi = p.get_hi_pos();
- p.bump();
- ret spanned(lo, hi, ast::cdir_src_mod(id, file_opt));
- }
-
- // mod x = "foo_dir" { ...directives... }
+ alt (p.peek()) {
- case (token::LBRACE) {
- p.bump();
- auto cdirs = parse_crate_directives(p, token::RBRACE);
- auto hi = p.get_hi_pos();
- expect(p, token::RBRACE);
- ret spanned(lo, hi,
- ast::cdir_dir_mod(id, file_opt, cdirs));
- }
+ // mod x = "foo.rs";
- case (?t) {
- unexpected(p, t);
- }
+ case (token::SEMI) {
+ auto hi = p.get_hi_pos();
+ p.bump();
+ ret spanned(lo, hi, ast::cdir_src_mod(id, file_opt));
}
- }
-
- case (token::LET) {
- p.bump();
- expect(p, token::LPAREN);
- auto id = parse_ident(p);
- expect(p, token::EQ);
- auto x = parse_expr(p);
- expect(p, token::RPAREN);
- expect(p, token::LBRACE);
- auto v = parse_crate_directives(p, token::RBRACE);
- auto hi = p.get_hi_pos();
- expect(p, token::RBRACE);
- ret spanned(lo, hi, ast::cdir_let(id, x, v));
- }
- case (token::USE) {
- auto vi = parse_view_item(p);
- ret spanned(lo, vi.span.hi, ast::cdir_view_item(vi));
- }
+ // mod x = "foo_dir" { ...directives... }
- case (token::IMPORT) {
- auto vi = parse_view_item(p);
- ret spanned(lo, vi.span.hi, ast::cdir_view_item(vi));
- }
-
- case (token::EXPORT) {
- auto vi = parse_view_item(p);
- ret spanned(lo, vi.span.hi, ast::cdir_view_item(vi));
- }
+ case (token::LBRACE) {
+ p.bump();
+ auto cdirs = parse_crate_directives(p, token::RBRACE);
+ auto hi = p.get_hi_pos();
+ expect(p, token::RBRACE);
+ ret spanned(lo, hi,
+ ast::cdir_dir_mod(id, file_opt, cdirs));
+ }
- case (_) {
- auto x = parse_expr(p);
- ret spanned(lo, x.span.hi, ast::cdir_expr(x));
+ case (?t) {
+ unexpected(p, t);
+ }
}
+ } else if (eat_word(p, "let")) {
+ expect(p, token::LPAREN);
+ auto id = parse_ident(p);
+ expect(p, token::EQ);
+ auto x = parse_expr(p);
+ expect(p, token::RPAREN);
+ expect(p, token::LBRACE);
+ auto v = parse_crate_directives(p, token::RBRACE);
+ auto hi = p.get_hi_pos();
+ expect(p, token::RBRACE);
+ ret spanned(lo, hi, ast::cdir_let(id, x, v));
+ } else if (is_word(p, "use")) {
+ auto vi = parse_view_item(p);
+ ret spanned(lo, vi.span.hi, ast::cdir_view_item(vi));
+ } else if (is_word(p, "import")) {
+ auto vi = parse_view_item(p);
+ ret spanned(lo, vi.span.hi, ast::cdir_view_item(vi));
+ } else if (is_word(p, "export")) {
+ auto vi = parse_view_item(p);
+ ret spanned(lo, vi.span.hi, ast::cdir_view_item(vi));
+ } else {
+ auto x = parse_expr(p);
+ ret spanned(lo, x.span.hi, ast::cdir_expr(x));
}
fail;
}