vicis_core/ir/module/metadata/
parser.rs1use crate::ir::module::{metadata::Metadata, name, name::Name};
2use crate::ir::{
3 types,
4 util::{spaces, string_literal},
5 value::parser::parse_constant_int,
6};
7use nom;
8use nom::{
9 branch::alt,
10 bytes::complete::tag,
11 character::complete::char,
12 error::VerboseError,
13 multi::separated_list0,
14 sequence::{preceded, separated_pair, tuple},
15 IResult,
16};
17
18pub fn parse(
19 types: &types::Types,
20) -> impl Fn(&str) -> IResult<&str, (Name, Metadata), VerboseError<&str>> + '_ {
21 move |source| {
22 separated_pair(
23 preceded(exclamation, name::parse),
24 preceded(spaces, tag("=")),
25 node(types),
26 )(source)
27 }
28}
29
30fn exclamation(source: &str) -> IResult<&str, &str, VerboseError<&str>> {
31 preceded(spaces, tag("!"))(source)
32}
33
34fn string(source: &str) -> IResult<&str, Metadata, VerboseError<&str>> {
35 preceded(exclamation, preceded(spaces, string_literal))(source)
36 .map(|(i, source)| (i, Metadata::String(source)))
37}
38
39fn name(source: &str) -> IResult<&str, Metadata, VerboseError<&str>> {
40 preceded(exclamation, name::parse)(source).map(|(i, source)| (i, Metadata::Name(source)))
41}
42
43fn int(types: &types::Types) -> impl Fn(&str) -> IResult<&str, Metadata, VerboseError<&str>> + '_ {
44 move |source| {
45 let (source, ty) = types::parse(source, types)?;
46 parse_constant_int(source, ty).map(|(source, v)| (source, Metadata::Int(v)))
47 }
48}
49
50fn node(types: &types::Types) -> impl Fn(&str) -> IResult<&str, Metadata, VerboseError<&str>> + '_ {
51 move |source| {
52 tuple((
53 exclamation,
54 spaces,
55 char('{'),
56 separated_list0(preceded(spaces, tag(",")), operand(types)),
57 spaces,
58 char('}'),
59 ))(source)
60 .map(|(i, (_, _, _, list, _, _))| (i, Metadata::Node(list)))
61 }
62}
63
64pub fn operand(
65 types: &types::Types,
66) -> impl Fn(&str) -> IResult<&str, Metadata, VerboseError<&str>> + '_ {
67 move |source| alt((string, name, node(types), int(types)))(source)
68}
69
70#[test]
71fn test1() {
72 use crate::ir::types::Types;
73 use nom::multi::many1;
74
75 let source = "
76 !llvm.module.flags = !{!0}
77 !llvm.ident = !{!1}
78 !0 = !{i32 1, !\"wchar_size\", i32 4}
79 !1 = !{!\"clang version 10.0.0-4ubuntu1 \"}
80 !llvm.module.flags = !{!0, !1, !2}
81 !0 = !{i32 7, !\"PIC Level\", i32 2}
82 !1 = !{i32 7, !\"PIE Level\", i32 2}
83 !2 = !{i32 2, !\"RtLibUseGOT\", i32 1}
84 !3 = !{}
85 !4 = !{i32 2849348}
86 !4 = !{i32 2849319}
87 !4 = !{i32 2849383}";
88
89 insta::assert_debug_snapshot!(many1(parse(&Types::new()))(source));
90}