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
use crate::ir::module::{metadata::Metadata, name, name::Name};
use crate::ir::{
types,
util::{spaces, string_literal},
value::parser::parse_constant_int,
};
use nom;
use nom::{
branch::alt,
bytes::complete::tag,
character::complete::char,
error::VerboseError,
multi::separated_list0,
sequence::{preceded, separated_pair, tuple},
IResult,
};
pub fn parse(
types: &types::Types,
) -> impl Fn(&str) -> IResult<&str, (Name, Metadata), VerboseError<&str>> + '_ {
move |source| {
separated_pair(
preceded(exclamation, name::parse),
preceded(spaces, tag("=")),
node(types),
)(source)
}
}
fn exclamation(source: &str) -> IResult<&str, &str, VerboseError<&str>> {
preceded(spaces, tag("!"))(source)
}
fn string(source: &str) -> IResult<&str, Metadata, VerboseError<&str>> {
preceded(exclamation, preceded(spaces, string_literal))(source)
.map(|(i, source)| (i, Metadata::String(source)))
}
fn name(source: &str) -> IResult<&str, Metadata, VerboseError<&str>> {
preceded(exclamation, name::parse)(source).map(|(i, source)| (i, Metadata::Name(source)))
}
fn int(types: &types::Types) -> impl Fn(&str) -> IResult<&str, Metadata, VerboseError<&str>> + '_ {
move |source| {
let (source, ty) = types::parse(source, types)?;
parse_constant_int(source, ty).map(|(source, v)| (source, Metadata::Int(v)))
}
}
fn node(types: &types::Types) -> impl Fn(&str) -> IResult<&str, Metadata, VerboseError<&str>> + '_ {
move |source| {
tuple((
exclamation,
spaces,
char('{'),
separated_list0(preceded(spaces, tag(",")), operand(types)),
spaces,
char('}'),
))(source)
.map(|(i, (_, _, _, list, _, _))| (i, Metadata::Node(list)))
}
}
pub fn operand(
types: &types::Types,
) -> impl Fn(&str) -> IResult<&str, Metadata, VerboseError<&str>> + '_ {
move |source| alt((string, name, node(types), int(types)))(source)
}
#[test]
fn test1() {
use crate::ir::types::Types;
use nom::multi::many1;
let source = "
!llvm.module.flags = !{!0}
!llvm.ident = !{!1}
!0 = !{i32 1, !\"wchar_size\", i32 4}
!1 = !{!\"clang version 10.0.0-4ubuntu1 \"}
!llvm.module.flags = !{!0, !1, !2}
!0 = !{i32 7, !\"PIC Level\", i32 2}
!1 = !{i32 7, !\"PIE Level\", i32 2}
!2 = !{i32 2, !\"RtLibUseGOT\", i32 1}
!3 = !{}
!4 = !{i32 2849348}
!4 = !{i32 2849319}
!4 = !{i32 2849383}";
insta::assert_debug_snapshot!(many1(parse(&Types::new()))(source));
}