1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
use nom::{Err as NomErr, ErrorKind, IResult, Needed};
use std::fmt;
use std::str::{from_utf8_unchecked};
use syntax;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ParseError {
kind: ErrorKind,
info: String
}
impl fmt::Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(f, "error ({:?}): {}", self.kind, self.info)
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum ParseResult<T> {
Ok(T),
Err(ParseError),
Incomplete(Needed)
}
fn run_parser<P, T>(source: &[u8], parser: P) -> ParseResult<T>
where P: FnOnce(&[u8]) -> IResult<&[u8], T> {
match parser(source) {
IResult::Done(i, x) => {
if i.is_empty() {
ParseResult::Ok(x)
} else {
let kind = ErrorKind::Custom(0); let msg = unsafe { from_utf8_unchecked(i).to_owned() };
let info = msg.lines().next().unwrap_or("").to_owned();
ParseResult::Err(ParseError { kind, info })
}
},
IResult::Error(err) => match err {
NomErr::Code(k) => ParseResult::Err(ParseError { kind: k, info: String::new() }),
NomErr::Node(kind, trace) => {
let info = format!("{:#?}", trace);
ParseResult::Err(ParseError { kind, info })
},
NomErr::Position(kind, p) => {
let msg = unsafe { from_utf8_unchecked(p).to_owned() };
let info = msg.lines().next().unwrap_or("").to_owned();
ParseResult::Err(ParseError { kind, info })
},
NomErr::NodePosition(kind, p, trace) => {
let p_msg = unsafe { from_utf8_unchecked(p) };
let info = format!("{}: {:#?}", p_msg, trace);
ParseResult::Err(ParseError { kind, info })
}
},
IResult::Incomplete(n) => ParseResult::Incomplete(n)
}
}
pub trait Parse: Sized {
fn parse<B>(source: B) -> ParseResult<Self> where B: AsRef<[u8]>;
fn parse_str<S>(source: S) -> ParseResult<Self> where S: AsRef<str> {
let s = source.as_ref().as_bytes();
Self::parse(s)
}
}
macro_rules! impl_parse {
($type_name:ty, $parser_name:ident) => {
impl Parse for $type_name {
fn parse<B>(source: B) -> ParseResult<Self> where B: AsRef<[u8]> {
run_parser(source.as_ref(), $crate::parsers::$parser_name)
}
}
}
}
impl_parse!(syntax::Identifier, identifier);
impl_parse!(syntax::TypeSpecifierNonArray, type_specifier_non_array);
impl_parse!(syntax::TypeSpecifier, type_specifier);
impl_parse!(syntax::UnaryOp, unary_op);
impl_parse!(syntax::StructFieldSpecifier, struct_field_specifier);
impl_parse!(syntax::StructSpecifier, struct_specifier);
impl_parse!(syntax::StorageQualifier, storage_qualifier);
impl_parse!(syntax::LayoutQualifier, layout_qualifier);
impl_parse!(syntax::PrecisionQualifier, precision_qualifier);
impl_parse!(syntax::InterpolationQualifier, interpolation_qualifier);
impl_parse!(syntax::TypeQualifier, type_qualifier);
impl_parse!(syntax::TypeQualifierSpec, type_qualifier_spec);
impl_parse!(syntax::FullySpecifiedType, fully_specified_type);
impl_parse!(syntax::ArraySpecifier, array_specifier);
impl_parse!(syntax::Expr, expr);
impl_parse!(syntax::Declaration, declaration);
impl_parse!(syntax::FunctionPrototype, function_prototype);
impl_parse!(syntax::InitDeclaratorList, init_declarator_list);
impl_parse!(syntax::SingleDeclaration, single_declaration);
impl_parse!(syntax::Initializer, initializer);
impl_parse!(syntax::FunIdentifier, function_identifier);
impl_parse!(syntax::AssignmentOp, assignment_op);
impl_parse!(syntax::SimpleStatement, simple_statement);
impl_parse!(syntax::ExprStatement, expr_statement);
impl_parse!(syntax::SelectionStatement, selection_statement);
impl_parse!(syntax::SwitchStatement, switch_statement);
impl_parse!(syntax::CaseLabel, case_label);
impl_parse!(syntax::IterationStatement, iteration_statement);
impl_parse!(syntax::JumpStatement, jump_statement);
impl_parse!(syntax::Condition, condition);
impl_parse!(syntax::Statement, statement);
impl_parse!(syntax::CompoundStatement, compound_statement);
impl_parse!(syntax::FunctionDefinition, function_definition);
impl_parse!(syntax::ExternalDeclaration, external_declaration);
impl_parse!(syntax::TranslationUnit, translation_unit);
impl_parse!(syntax::Preprocessor, preprocessor);
impl_parse!(syntax::PreprocessorVersion, pp_version);
impl_parse!(syntax::PreprocessorVersionProfile, pp_version_profile);
impl_parse!(syntax::PreprocessorExtensionName, pp_extension_name);
impl_parse!(syntax::PreprocessorExtensionBehavior, pp_extension_behavior);
impl_parse!(syntax::PreprocessorExtension, pp_extension);