1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! The main parser interface
16 use codemap::{span, CodeMap, FileMap, CharPos, BytePos};
18 use diagnostic::{span_handler, mk_span_handler, mk_handler, Emitter};
19 use parse::attr::parser_attr;
20 use parse::lexer::{reader, StringReader};
21 use parse::parser::Parser;
22 use parse::token::{ident_interner, mk_ident_interner};
26 use core::option::{None, Option, Some};
28 use core::result::{Err, Ok, Result};
38 /// Common routines shared by parser mods
41 /// Functions dealing with operator precedence
44 /// Routines the parser uses to classify AST nodes
47 /// Reporting obsolete syntax
50 pub struct ParseSess {
51 cm: @codemap::CodeMap,
53 span_diagnostic: span_handler,
54 interner: @ident_interner,
57 pub fn new_parse_sess(demitter: Option<Emitter>) -> @mut ParseSess {
58 let cm = @CodeMap::new();
62 span_diagnostic: mk_span_handler(mk_handler(demitter), cm),
63 interner: mk_ident_interner(),
67 pub fn new_parse_sess_special_handler(sh: span_handler, cm: @codemap::CodeMap)
73 interner: mk_ident_interner(),
77 pub fn parse_crate_from_file(input: &Path, cfg: ast::crate_cfg,
78 sess: @mut ParseSess) -> @ast::crate {
79 let p = new_crate_parser_from_file(sess, cfg, input);
80 let r = p.parse_crate_mod(cfg);
84 pub fn parse_crate_from_source_str(name: ~str,
87 sess: @mut ParseSess) -> @ast::crate {
88 let p = new_parser_from_source_str(sess, cfg, name,
89 codemap::FssNone, source);
90 let r = p.parse_crate_mod(cfg);
95 pub fn parse_expr_from_source_str(name: ~str,
98 sess: @mut ParseSess) -> @ast::expr {
99 let p = new_parser_from_source_str(sess, cfg, name,
100 codemap::FssNone, source);
101 let r = p.parse_expr();
106 pub fn parse_item_from_source_str(name: ~str,
109 +attrs: ~[ast::attribute],
110 sess: @mut ParseSess)
111 -> Option<@ast::item> {
112 let p = new_parser_from_source_str(sess, cfg, name,
113 codemap::FssNone, source);
114 let r = p.parse_item(attrs);
119 pub fn parse_stmt_from_source_str(name: ~str,
122 +attrs: ~[ast::attribute],
123 sess: @mut ParseSess) -> @ast::stmt {
124 let p = new_parser_from_source_str(sess, cfg, name,
125 codemap::FssNone, source);
126 let r = p.parse_stmt(attrs);
131 pub fn parse_tts_from_source_str(name: ~str,
134 sess: @mut ParseSess) -> ~[ast::token_tree] {
135 let p = new_parser_from_source_str(sess, cfg, name,
136 codemap::FssNone, source);
138 let r = p.parse_all_token_trees();
143 pub fn parse_from_source_str<T>(f: fn (p: Parser) -> T,
144 name: ~str, ss: codemap::FileSubstr,
145 source: @~str, cfg: ast::crate_cfg,
146 sess: @mut ParseSess)
149 let p = new_parser_from_source_str(sess, cfg, name, ss,
152 if !p.reader.is_eof() {
153 p.reader.fatal(~"expected end-of-string");
159 pub fn next_node_id(sess: @mut ParseSess) -> node_id {
160 let rv = sess.next_id;
162 // ID 0 is reserved for the crate and doesn't actually exist in the AST
167 pub fn new_parser_from_source_str(sess: @mut ParseSess, cfg: ast::crate_cfg,
168 +name: ~str, +ss: codemap::FileSubstr,
169 source: @~str) -> Parser {
170 let filemap = sess.cm.new_filemap_w_substr(name, ss, source);
171 let srdr = lexer::new_string_reader(copy sess.span_diagnostic,
174 return Parser(sess, cfg, srdr as reader);
177 pub fn new_parser_from_file(sess: @mut ParseSess,
180 -> Result<Parser, ~str> {
181 match io::read_whole_file_str(path) {
184 let filemap = sess.cm.new_filemap(path.to_str(), @src);
185 let srdr = lexer::new_string_reader(copy sess.span_diagnostic,
188 Ok(Parser(sess, cfg, srdr as reader))
191 result::Err(e) => Err(e)
195 /// Create a new parser for an entire crate, handling errors as appropriate
196 /// if the file doesn't exist
197 pub fn new_crate_parser_from_file(sess: @mut ParseSess, cfg: ast::crate_cfg,
198 path: &Path) -> Parser {
199 match new_parser_from_file(sess, cfg, path) {
200 Ok(parser) => parser,
202 sess.span_diagnostic.handler().fatal(e)
207 /// Create a new parser based on a span from an existing parser. Handles
208 /// error messages correctly when the file does not exist.
209 pub fn new_sub_parser_from_file(sess: @mut ParseSess, cfg: ast::crate_cfg,
210 path: &Path, sp: span) -> Parser {
211 match new_parser_from_file(sess, cfg, path) {
212 Ok(parser) => parser,
214 sess.span_diagnostic.span_fatal(sp, e)
219 pub fn new_parser_from_tts(sess: @mut ParseSess, cfg: ast::crate_cfg,
220 tts: ~[ast::token_tree]) -> Parser {
221 let trdr = lexer::new_tt_reader(copy sess.span_diagnostic, sess.interner,
223 return Parser(sess, cfg, trdr as reader)
230 use std::serialize::Encodable;
233 use util::testing::*;
235 #[test] fn to_json_str (val: Encodable<std::json::Encoder>) -> ~str {
236 let bw = @io::BytesWriter();
237 val.encode(~std::json::Encoder(bw as io::Writer));
238 str::from_bytes(bw.bytes.data)
241 #[test] fn alltts () {
242 let tts = parse_tts_from_source_str(
244 @~"fn foo (x : int) { x; }",
246 new_parse_sess(None));
247 check_equal(to_json_str(tts as Encodable::<std::json::Encoder>),
248 ~"[[\"tt_tok\",[,[\"IDENT\",[\"fn\",false]]]],\
249 [\"tt_tok\",[,[\"IDENT\",[\"foo\",false]]]],\
250 [\"tt_delim\",[[[\"tt_tok\",[,[\"LPAREN\",[]]]],\
251 [\"tt_tok\",[,[\"IDENT\",[\"x\",false]]]],\
252 [\"tt_tok\",[,[\"COLON\",[]]]],\
253 [\"tt_tok\",[,[\"IDENT\",[\"int\",false]]]],\
254 [\"tt_tok\",[,[\"RPAREN\",[]]]]]]],\
255 [\"tt_delim\",[[[\"tt_tok\",[,[\"LBRACE\",[]]]],\
256 [\"tt_tok\",[,[\"IDENT\",[\"x\",false]]]],\
257 [\"tt_tok\",[,[\"SEMI\",[]]]],\
258 [\"tt_tok\",[,[\"RBRACE\",[]]]]]]]]"
260 let ast1 = new_parser_from_tts(new_parse_sess(None),~[],tts)
262 let ast2 = parse_item_from_source_str(
264 @~"fn foo (x : int) { x; }",
266 new_parse_sess(None));
267 check_equal(ast1,ast2);
275 // indent-tabs-mode: nil
277 // buffer-file-coding-system: utf-8-unix