1mod error;
2mod parser;
3pub mod types;
4mod util;
5
6use nom::{
7 branch::alt, combinator::map_res, multi::separated_list1, sequence::terminated, IResult,
8};
9
10use crate::error::Error;
11use std::convert;
12use std::fs::File;
13use std::io::Read;
14use std::path;
15
16#[derive(Debug)]
17pub enum Definition {
18 Type(types::TypeDef),
19 Data(types::DataDef),
20 Func(types::FuncDef),
21}
22
23fn parse_def(input: &str) -> IResult<&str, Definition> {
24 alt((
25 map_res(parser::typedef, |ty| -> Result<Definition, ()> {
26 Ok(Definition::Type(ty))
27 }),
28 map_res(parser::datadef, |data| -> Result<Definition, ()> {
29 Ok(Definition::Data(data))
30 }),
31 map_res(parser::funcdef, |func| -> Result<Definition, ()> {
32 Ok(Definition::Func(func))
33 }),
34 ))(input)
35}
36
37fn parse_defs(input: &str) -> IResult<&str, Vec<Definition>> {
38 terminated(
39 separated_list1(util::ws(util::newline0), parse_def),
40 util::newline0,
41 )(input)
42}
43
44////////////////////////////////////////////////////////////////////////
45
46pub fn parse_file<'a, P: convert::AsRef<path::Path>>(fp: P) -> Result<Vec<Definition>, Error> {
47 let mut file = File::open(fp)?;
48
49 // TODO: mmap(2) file instead of reading it into memory.
50 let mut buf = String::new();
51 file.read_to_string(&mut buf)?;
52
53 let (input, defs) = parse_defs(&buf)?;
54 if input != "" {
55 Err(Error::IncompleteParse)
56 } else {
57 Ok(defs)
58 }
59}