xshade_parser/parser/
mod.rs

1use nom::types::CompleteStr;
2use nom::{Err, ErrorKind, Context};
3use nom_locate::LocatedSpan;
4use ::ast::*;
5use ::error::*;
6
7mod expressions;
8
9mod ws;
10mod identifier;
11mod structs;
12mod functions;
13mod types;
14
15use self::ws::*;
16pub use self::identifier::*;
17pub use self::structs::*;
18pub use self::functions::*;
19pub use self::types::*;
20pub use self::expressions::*;
21
22pub type NomSpan<'a> = LocatedSpan<CompleteStr<'a>>;
23
24named!(parse_number<NomSpan, NomSpan>,
25    recognize!(
26        do_parse!(
27            many1!(one_of!("0123456789")) >>
28            ()
29        )
30    )
31);
32
33named!(parse_operator<NomSpan, OperatorType>,
34    alt!(
35        do_parse!(char!('+') >> (OperatorType::Plus)) |
36        do_parse!(char!('-') >> (OperatorType::Minus)) |
37        do_parse!(char!('*') >> (OperatorType::Multiply)) |
38        do_parse!(char!('/') >> (OperatorType::Divide))
39    )
40);
41
42named!(parse_local_statement<NomSpan, Statement>,
43    do_parse!(
44        from: ws!(tag!("let")) >>
45        symbol_name: parse_identifier >>
46        ws!(tag!("=")) >>
47        expression: parse_expression >>
48        to: ws!(tag!(";")) >>
49        (Statement::Local(
50            LocalStatement{
51                span: Span::from_to(Span::from_nom_span(&from), Span::from_nom_span(&to)),
52                symbol_name: symbol_name,
53                expression: expression,
54            }
55        ))
56    )
57);
58
59named!(parse_return_statement<NomSpan, Statement>,
60    do_parse!(
61        from: ws!(tag!("return")) >>
62        expression: parse_expression >>
63        to: ws!(tag!(";")) >>
64        (Statement::Return(ReturnStatement{
65            span: Span::from_to(Span::from_nom_span(&from), Span::from_nom_span(&to)),
66            expression: expression,
67        }))
68    )
69);
70
71named!(parse_expression_statement<NomSpan, Statement>,
72    do_parse!(
73        expression: parse_expression >>
74        semicolon: ws!(tag!(";")) >>
75        (Statement::Expression(
76            ExpressionStatement {
77                span: Span::from_to(expression.get_span(), Span::from_nom_span(&semicolon)),
78                expression,
79            }
80        ))
81    )
82);
83
84named!(parse_block_statements<NomSpan, Vec<Statement>>,
85    many0!(
86        ws!(
87            alt!(
88                parse_local_statement |
89                parse_return_statement |
90                parse_expression_statement
91            )
92        )
93    )
94);
95
96named!(parse_block_declaration<NomSpan, BlockDeclaration>,
97    do_parse!(
98        from: ws!(tag!("{")) >>
99        statements: parse_block_statements >>
100        to: ws!(tag!("}")) >>
101        (BlockDeclaration{
102            span: Span::from_to(Span::from_nom_span(&from), Span::from_nom_span(&to)),
103            statements: statements,
104        })
105    )
106);
107
108named!(parse<NomSpan, Ast>,
109    do_parse!(
110        ws0 >>
111        ast: many0!(
112            alt!(
113                parse_struct |
114                parse_function
115            )
116        ) >>
117        ws0 >>
118        return_error!(add_return_error!(ErrorKind::Custom(ParseErrorKind::InvalidTopLevelItem as u32), eof!())) >>
119        (ast)
120    )
121);
122
123/// Parses a string into an untyped AST
124/// 
125/// # Example
126/// ```
127/// # extern crate xshade_parser;
128/// # use xshade_parser::parse_str;
129/// let ast = parse_str("struct Foo { bar: f32, }").unwrap();
130/// ```
131pub fn parse_str(program: &str) -> ParseResult<Ast> {
132    let input = NomSpan::new(CompleteStr(program));
133    let output = parse(input);
134
135    match output {
136        Ok((remaining, ast)) => {
137            if remaining.fragment.len() > 0 {
138                unimplemented!("handle remaining")
139            }
140
141            Ok(ast)
142        },
143        Err(Err::Incomplete(_needed)) => {
144            Err(ParseError::new(Span::new(0, 0, 0, 0), ParseErrorKind::MissingError))
145        },
146        Err(Err::Error(error)) | Err(Err::Failure(error)) => {
147            match error {
148                Context::Code(span, ErrorKind::Custom(error_number)) => {
149                    return Err(ParseError::new(
150                        Span::from_nom_span(&span),
151                        ParseErrorKind::from(error_number)
152                    ));
153                }
154
155                Context::Code(span, _error_kind) => {
156                    println!("{:#?}", _error_kind);
157                    return Err(ParseError::new(
158                        Span::from_nom_span(&span),
159                        ParseErrorKind::MissingError,
160                    ));
161                }
162            }
163        },
164    }
165}