Skip to main content

vicis_core/ir/module/metadata/
parser.rs

1use 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}