|
| 1 | +export parse_sess; |
| 2 | +export next_node_id; |
| 3 | +export new_parser_from_file; |
| 4 | +export new_parser_from_source_str; |
| 5 | +export parse_crate_from_file; |
| 6 | +export parse_crate_from_crate_file; |
| 7 | +export parse_crate_from_source_str; |
| 8 | +export parse_expr_from_source_str; |
| 9 | +export parse_from_source_str; |
| 10 | + |
| 11 | +import parser::parser; |
| 12 | +import ast::node_id; |
| 13 | +import util::interner; |
| 14 | +import lexer::reader; |
| 15 | + |
| 16 | +type parse_sess = @{ |
| 17 | + cm: codemap::codemap, |
| 18 | + mut next_id: node_id, |
| 19 | + span_diagnostic: diagnostic::span_handler, |
| 20 | + // these two must be kept up to date |
| 21 | + mut chpos: uint, |
| 22 | + mut byte_pos: uint |
| 23 | +}; |
| 24 | + |
| 25 | +fn next_node_id(sess: parse_sess) -> node_id { |
| 26 | + let rv = sess.next_id; |
| 27 | + sess.next_id += 1; |
| 28 | + // ID 0 is reserved for the crate and doesn't actually exist in the AST |
| 29 | + assert rv != 0; |
| 30 | + ret rv; |
| 31 | +} |
| 32 | + |
| 33 | +fn new_parser_from_file(sess: parse_sess, cfg: ast::crate_cfg, path: str, |
| 34 | + ftype: parser::file_type) -> |
| 35 | + parser { |
| 36 | + let src = alt io::read_whole_file_str(path) { |
| 37 | + result::ok(src) { |
| 38 | + // FIXME: This copy is unfortunate |
| 39 | + @src |
| 40 | + } |
| 41 | + result::err(e) { |
| 42 | + sess.span_diagnostic.handler().fatal(e) |
| 43 | + } |
| 44 | + }; |
| 45 | + let filemap = codemap::new_filemap(path, src, |
| 46 | + sess.chpos, sess.byte_pos); |
| 47 | + sess.cm.files += [filemap]; |
| 48 | + let itr = @interner::mk(str::hash, str::eq); |
| 49 | + let rdr = lexer::new_reader(sess.span_diagnostic, filemap, itr); |
| 50 | + ret new_parser(sess, cfg, rdr, ftype); |
| 51 | +} |
| 52 | + |
| 53 | +fn new_parser_from_source_str(sess: parse_sess, cfg: ast::crate_cfg, |
| 54 | + name: str, ss: codemap::file_substr, |
| 55 | + source: @str) -> parser { |
| 56 | + let ftype = parser::SOURCE_FILE; |
| 57 | + let filemap = codemap::new_filemap_w_substr |
| 58 | + (name, ss, source, sess.chpos, sess.byte_pos); |
| 59 | + sess.cm.files += [filemap]; |
| 60 | + let itr = @interner::mk(str::hash, str::eq); |
| 61 | + let rdr = lexer::new_reader(sess.span_diagnostic, |
| 62 | + filemap, itr); |
| 63 | + ret new_parser(sess, cfg, rdr, ftype); |
| 64 | +} |
| 65 | + |
| 66 | +fn new_parser(sess: parse_sess, cfg: ast::crate_cfg, rdr: lexer::reader, |
| 67 | + ftype: parser::file_type) -> parser { |
| 68 | + let tok0 = lexer::next_token(rdr); |
| 69 | + let span0 = ast_util::mk_sp(tok0.chpos, rdr.chpos); |
| 70 | + @{sess: sess, |
| 71 | + cfg: cfg, |
| 72 | + file_type: ftype, |
| 73 | + mut token: tok0.tok, |
| 74 | + mut span: span0, |
| 75 | + mut last_span: span0, |
| 76 | + mut buffer: [], |
| 77 | + mut restriction: parser::UNRESTRICTED, |
| 78 | + reader: rdr, |
| 79 | + binop_precs: prec::binop_prec_table(), |
| 80 | + bad_expr_words: token::bad_expr_word_table()} |
| 81 | +} |
| 82 | + |
| 83 | +fn parse_crate_from_crate_file(input: str, cfg: ast::crate_cfg, |
| 84 | + sess: parse_sess) -> @ast::crate { |
| 85 | + let p = new_parser_from_file(sess, cfg, input, parser::CRATE_FILE); |
| 86 | + let lo = p.span.lo; |
| 87 | + let prefix = path::dirname(p.reader.filemap.name); |
| 88 | + let leading_attrs = parser::parse_inner_attrs_and_next(p); |
| 89 | + let crate_attrs = leading_attrs.inner; |
| 90 | + let first_cdir_attr = leading_attrs.next; |
| 91 | + let cdirs = parser::parse_crate_directives( |
| 92 | + p, token::EOF, first_cdir_attr); |
| 93 | + sess.chpos = p.reader.chpos; |
| 94 | + sess.byte_pos = sess.byte_pos + p.reader.pos; |
| 95 | + let cx = |
| 96 | + @{p: p, |
| 97 | + sess: sess, |
| 98 | + cfg: p.cfg}; |
| 99 | + let (companionmod, _) = path::splitext(path::basename(input)); |
| 100 | + let (m, attrs) = eval::eval_crate_directives_to_mod( |
| 101 | + cx, cdirs, prefix, option::some(companionmod)); |
| 102 | + let mut hi = p.span.hi; |
| 103 | + parser::expect(p, token::EOF); |
| 104 | + ret @ast_util::respan(ast_util::mk_sp(lo, hi), |
| 105 | + {directives: cdirs, |
| 106 | + module: m, |
| 107 | + attrs: crate_attrs + attrs, |
| 108 | + config: p.cfg}); |
| 109 | +} |
| 110 | + |
| 111 | +fn parse_crate_from_file(input: str, cfg: ast::crate_cfg, sess: parse_sess) -> |
| 112 | + @ast::crate { |
| 113 | + if str::ends_with(input, ".rc") { |
| 114 | + parse_crate_from_crate_file(input, cfg, sess) |
| 115 | + } else if str::ends_with(input, ".rs") { |
| 116 | + parse_crate_from_source_file(input, cfg, sess) |
| 117 | + } else { |
| 118 | + sess.span_diagnostic.handler().fatal("unknown input file type: " + |
| 119 | + input) |
| 120 | + } |
| 121 | +} |
| 122 | + |
| 123 | +fn parse_crate_from_source_file(input: str, cfg: ast::crate_cfg, |
| 124 | + sess: parse_sess) -> @ast::crate { |
| 125 | + let p = new_parser_from_file(sess, cfg, input, parser::SOURCE_FILE); |
| 126 | + let r = parser::parse_crate_mod(p, cfg); |
| 127 | + sess.chpos = p.reader.chpos; |
| 128 | + sess.byte_pos = sess.byte_pos + p.reader.pos; |
| 129 | + ret r; |
| 130 | +} |
| 131 | + |
| 132 | +fn parse_expr_from_source_str(name: str, source: @str, cfg: ast::crate_cfg, |
| 133 | + sess: parse_sess) -> @ast::expr { |
| 134 | + let p = new_parser_from_source_str( |
| 135 | + sess, cfg, name, codemap::fss_none, source); |
| 136 | + let r = parser::parse_expr(p); |
| 137 | + sess.chpos = p.reader.chpos; |
| 138 | + sess.byte_pos = sess.byte_pos + p.reader.pos; |
| 139 | + ret r; |
| 140 | +} |
| 141 | + |
| 142 | +fn parse_crate_from_source_str(name: str, source: @str, cfg: ast::crate_cfg, |
| 143 | + sess: parse_sess) -> @ast::crate { |
| 144 | + let p = new_parser_from_source_str( |
| 145 | + sess, cfg, name, codemap::fss_none, source); |
| 146 | + let r = parser::parse_crate_mod(p, cfg); |
| 147 | + sess.chpos = p.reader.chpos; |
| 148 | + sess.byte_pos = sess.byte_pos + p.reader.pos; |
| 149 | + ret r; |
| 150 | +} |
| 151 | + |
| 152 | +fn parse_from_source_str<T>(f: fn (p: parser) -> T, |
| 153 | + name: str, ss: codemap::file_substr, |
| 154 | + source: @str, cfg: ast::crate_cfg, |
| 155 | + sess: parse_sess) |
| 156 | + -> T |
| 157 | +{ |
| 158 | + let p = new_parser_from_source_str(sess, cfg, name, ss, source); |
| 159 | + let r = f(p); |
| 160 | + if !p.reader.is_eof() { |
| 161 | + p.reader.fatal("expected end-of-string"); |
| 162 | + } |
| 163 | + sess.chpos = p.reader.chpos; |
| 164 | + sess.byte_pos = sess.byte_pos + p.reader.pos; |
| 165 | + ret r; |
| 166 | +} |
0 commit comments