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
use nom::branch::alt;
use nom::bytes::complete::tag;
use nom::combinator::map;
use nom::sequence::{pair, preceded, tuple};
use nom::IResult;

use crate::basic::{Identifier, Literal, Separator};
use crate::Parser;

// Include         ::=  'include' Literal
#[derive(derive_newtype::NewType, Eq, PartialEq, Debug, Clone)]
pub struct Include<'a>(Literal<'a>);

impl<'a> Parser<'a> for Include<'a> {
    fn parse(input: &'a str) -> IResult<&'a str, Self> {
        map(
            preceded(pair(tag("include"), Separator::parse), Literal::parse),
            Self,
        )(input)
    }
}

// CppInclude      ::=  'cpp_include' Literal
#[derive(derive_newtype::NewType, Eq, PartialEq, Debug, Clone)]
pub struct CppInclude<'a>(Literal<'a>);

impl<'a> Parser<'a> for CppInclude<'a> {
    fn parse(input: &'a str) -> IResult<&'a str, Self> {
        map(
            preceded(pair(tag("cpp_include"), Separator::parse), Literal::parse),
            Self,
        )(input)
    }
}

// Namespace       ::=  ( 'namespace' ( NamespaceScope Identifier ) )
#[derive(Eq, PartialEq, Debug, Clone)]
pub struct Namespace<'a> {
    pub scope: NamespaceScope<'a>,
    pub name: Identifier<'a>,
}

// NamespaceScope  ::=  '*' | 'c_glib' | 'rust' | 'cpp' | 'delphi' | 'haxe' | 'go' | 'java' |
// 'js' | 'lua' | 'netstd' | 'perl' | 'php' | 'py' | 'py.twisted' | 'rb' | 'st' | 'xsd'
// We add rust into it.
#[derive(derive_newtype::NewType, Eq, PartialEq, Debug, Clone)]
pub struct NamespaceScope<'a>(&'a str);

impl<'a> Parser<'a> for Namespace<'a> {
    fn parse(input: &'a str) -> IResult<&'a str, Self> {
        map(
            tuple((
                tag("namespace"),
                preceded(Separator::parse, NamespaceScope::parse),
                preceded(Separator::parse, Identifier::parse),
            )),
            |(_, scope, name)| Self { scope, name },
        )(input)
    }
}

impl<'a> Parser<'a> for NamespaceScope<'a> {
    fn parse(input: &'a str) -> IResult<&'a str, Self> {
        map(
            alt((
                tag("*"),
                tag("c_glib"),
                tag("rust"),
                tag("cpp"),
                tag("delphi"),
                tag("haxe"),
                tag("go"),
                tag("java"),
                tag("js"),
                tag("lua"),
                tag("netstd"),
                tag("perl"),
                tag("php"),
                tag("py"),
                tag("py.twisted"),
                tag("rb"),
                tag("st"),
                tag("xsd"),
            )),
            Self,
        )(input)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_include() {
        assert_eq!(
            Include::parse("include 'another.thrift'").unwrap().1,
            Include::from(Literal::from("another.thrift"))
        )
    }

    #[test]
    fn test_namespace() {
        assert_eq!(
            Namespace::parse("namespace * MyNamespace").unwrap().1,
            Namespace {
                scope: NamespaceScope::from("*"),
                name: Identifier::from("MyNamespace")
            }
        )
    }
}