rust/src/libsyntax/parse.rs
2012-10-15 15:35:36 -07:00

220 lines
8.2 KiB
Rust

//! The main parser interface
export parse_sess;
export new_parse_sess, new_parse_sess_special_handler;
export next_node_id;
export new_parser_from_file, new_parser_etc_from_file;
export new_parser_from_source_str;
export new_parser_from_tt;
export parse_crate_from_file, parse_crate_from_crate_file;
export parse_crate_from_source_str;
export parse_expr_from_source_str, parse_item_from_source_str;
export parse_stmt_from_source_str;
export parse_from_source_str;
use parser::Parser;
use attr::parser_attr;
use common::parser_common;
use ast::node_id;
use util::interner;
use diagnostic::{span_handler, mk_span_handler, mk_handler, emitter};
use lexer::{reader, string_reader};
use parse::token::{ident_interner, mk_ident_interner};
type parse_sess = @{
cm: codemap::CodeMap,
mut next_id: node_id,
span_diagnostic: span_handler,
interner: @ident_interner,
// these two must be kept up to date
mut chpos: uint,
mut byte_pos: uint
};
fn new_parse_sess(demitter: Option<emitter>) -> parse_sess {
let cm = codemap::new_codemap();
return @{cm: cm,
mut next_id: 1,
span_diagnostic: mk_span_handler(mk_handler(demitter), cm),
interner: mk_ident_interner(),
mut chpos: 0u, mut byte_pos: 0u};
}
fn new_parse_sess_special_handler(sh: span_handler, cm: codemap::CodeMap)
-> parse_sess {
return @{cm: cm,
mut next_id: 1,
span_diagnostic: sh,
interner: mk_ident_interner(),
mut chpos: 0u, mut byte_pos: 0u};
}
fn parse_crate_from_file(input: &Path, cfg: ast::crate_cfg,
sess: parse_sess) -> @ast::crate {
if input.filetype() == Some(~".rc") {
parse_crate_from_crate_file(input, cfg, sess)
} else if input.filetype() == Some(~".rs") {
parse_crate_from_source_file(input, cfg, sess)
} else {
sess.span_diagnostic.handler().fatal(~"unknown input file type: " +
input.to_str())
}
}
fn parse_crate_from_crate_file(input: &Path, cfg: ast::crate_cfg,
sess: parse_sess) -> @ast::crate {
let (p, rdr) = new_parser_etc_from_file(sess, cfg, input,
parser::CRATE_FILE);
let lo = p.span.lo;
let prefix = input.dir_path();
let leading_attrs = p.parse_inner_attrs_and_next();
let { inner: crate_attrs, next: first_cdir_attr } = leading_attrs;
let cdirs = p.parse_crate_directives(token::EOF, first_cdir_attr);
sess.chpos = rdr.chpos;
sess.byte_pos = sess.byte_pos + rdr.pos;
let cx = @{sess: sess, cfg: /* FIXME (#2543) */ copy p.cfg};
let companionmod = input.filestem().map(|s| Path(*s));
let (m, attrs) = eval::eval_crate_directives_to_mod(
cx, cdirs, &prefix, &companionmod);
let mut hi = p.span.hi;
p.expect(token::EOF);
p.abort_if_errors();
return @ast_util::respan(ast_util::mk_sp(lo, hi),
{directives: cdirs,
module: m,
attrs: vec::append(crate_attrs, attrs),
config: /* FIXME (#2543) */ copy p.cfg});
}
fn parse_crate_from_source_file(input: &Path, cfg: ast::crate_cfg,
sess: parse_sess) -> @ast::crate {
let (p, rdr) = new_parser_etc_from_file(sess, cfg, input,
parser::SOURCE_FILE);
let r = p.parse_crate_mod(cfg);
sess.chpos = rdr.chpos;
sess.byte_pos = sess.byte_pos + rdr.pos;
return r;
}
fn parse_crate_from_source_str(name: ~str, source: @~str, cfg: ast::crate_cfg,
sess: parse_sess) -> @ast::crate {
let (p, rdr) = new_parser_etc_from_source_str(sess, cfg, name,
codemap::fss_none, source);
let r = p.parse_crate_mod(cfg);
p.abort_if_errors();
sess.chpos = rdr.chpos;
sess.byte_pos = sess.byte_pos + rdr.pos;
return r;
}
fn parse_expr_from_source_str(name: ~str, source: @~str, cfg: ast::crate_cfg,
sess: parse_sess) -> @ast::expr {
let (p, rdr) = new_parser_etc_from_source_str(sess, cfg, name,
codemap::fss_none, source);
let r = p.parse_expr();
p.abort_if_errors();
sess.chpos = rdr.chpos;
sess.byte_pos = sess.byte_pos + rdr.pos;
return r;
}
fn parse_item_from_source_str(name: ~str, source: @~str, cfg: ast::crate_cfg,
+attrs: ~[ast::attribute],
sess: parse_sess) -> Option<@ast::item> {
let (p, rdr) = new_parser_etc_from_source_str(sess, cfg, name,
codemap::fss_none, source);
let r = p.parse_item(attrs);
p.abort_if_errors();
sess.chpos = rdr.chpos;
sess.byte_pos = sess.byte_pos + rdr.pos;
return r;
}
fn parse_stmt_from_source_str(name: ~str, source: @~str, cfg: ast::crate_cfg,
+attrs: ~[ast::attribute],
sess: parse_sess) -> @ast::stmt {
let (p, rdr) = new_parser_etc_from_source_str(sess, cfg, name,
codemap::fss_none, source);
let r = p.parse_stmt(attrs);
p.abort_if_errors();
sess.chpos = rdr.chpos;
sess.byte_pos = sess.byte_pos + rdr.pos;
return r;
}
fn parse_from_source_str<T>(f: fn (p: Parser) -> T,
name: ~str, ss: codemap::file_substr,
source: @~str, cfg: ast::crate_cfg,
sess: parse_sess)
-> T
{
let (p, rdr) = new_parser_etc_from_source_str(sess, cfg, name, ss,
source);
let r = f(p);
if !p.reader.is_eof() {
p.reader.fatal(~"expected end-of-string");
}
p.abort_if_errors();
sess.chpos = rdr.chpos;
sess.byte_pos = sess.byte_pos + rdr.pos;
move r
}
fn next_node_id(sess: parse_sess) -> node_id {
let rv = sess.next_id;
sess.next_id += 1;
// ID 0 is reserved for the crate and doesn't actually exist in the AST
assert rv != 0;
return rv;
}
fn new_parser_etc_from_source_str(sess: parse_sess, cfg: ast::crate_cfg,
+name: ~str, +ss: codemap::file_substr,
source: @~str) -> (Parser, string_reader) {
let ftype = parser::SOURCE_FILE;
let filemap = codemap::new_filemap_w_substr
(name, ss, source, sess.chpos, sess.byte_pos);
sess.cm.files.push(filemap);
let srdr = lexer::new_string_reader(sess.span_diagnostic, filemap,
sess.interner);
return (Parser(sess, cfg, srdr as reader, ftype), srdr);
}
fn new_parser_from_source_str(sess: parse_sess, cfg: ast::crate_cfg,
+name: ~str, +ss: codemap::file_substr,
source: @~str) -> Parser {
let (p, _) = new_parser_etc_from_source_str(sess, cfg, name, ss, source);
move p
}
fn new_parser_etc_from_file(sess: parse_sess, cfg: ast::crate_cfg,
path: &Path, ftype: parser::file_type) ->
(Parser, string_reader) {
let res = io::read_whole_file_str(path);
match res {
result::Ok(_) => { /* Continue. */ }
result::Err(e) => sess.span_diagnostic.handler().fatal(e)
}
let src = @result::unwrap(res);
let filemap = codemap::new_filemap(path.to_str(), src,
sess.chpos, sess.byte_pos);
sess.cm.files.push(filemap);
let srdr = lexer::new_string_reader(sess.span_diagnostic, filemap,
sess.interner);
return (Parser(sess, cfg, srdr as reader, ftype), srdr);
}
fn new_parser_from_file(sess: parse_sess, cfg: ast::crate_cfg, path: &Path,
ftype: parser::file_type) -> Parser {
let (p, _) = new_parser_etc_from_file(sess, cfg, path, ftype);
move p
}
fn new_parser_from_tt(sess: parse_sess, cfg: ast::crate_cfg,
tt: ~[ast::token_tree]) -> Parser {
let trdr = lexer::new_tt_reader(sess.span_diagnostic, sess.interner,
None, tt);
return Parser(sess, cfg, trdr as reader, parser::SOURCE_FILE)
}