1use std::ops::Deref;
2
3use nom::{error::Error, Err};
4use nom_locate::LocatedSpan;
5
6mod parser;
7
8type Span<'a> = LocatedSpan<&'a str>;
9
10#[derive(Debug)]
11pub enum Sundry<'a> {
12 Comment(Span<'a>),
13 Empty(Span<'a>),
14 EOF,
15}
16
17#[derive(Debug, PartialEq, Eq)]
18pub enum Identifier<'a> {
19 Raw(&'a str),
20 Interpreted(String),
21}
22
23impl Deref for Identifier<'_> {
24 type Target = str;
25
26 fn deref(&self) -> &Self::Target {
27 match self {
28 Self::Raw(s) => s,
29 Self::Interpreted(s) => s.as_str(),
30 }
31 }
32}
33
34#[derive(Debug, PartialEq, Eq)]
35pub enum RetractSpec<'a> {
36 Version(Identifier<'a>),
37 Range((Identifier<'a>, Identifier<'a>)),
38}
39
40#[derive(Debug, PartialEq, Eq)]
41pub struct ReplaceSpec<'a> {
42 pub module_path: &'a str,
43 pub version: Option<Identifier<'a>>,
44 pub replacement: Replacement<'a>,
45}
46
47#[derive(Debug, PartialEq, Eq)]
48pub enum Replacement<'a> {
49 FilePath(Identifier<'a>),
50 Module((&'a str, Identifier<'a>)),
51}
52
53#[derive(Debug, PartialEq, Eq)]
55pub enum Directive<'a> {
56 Module {
57 module_path: &'a str,
58 },
59 Go {
60 version: Identifier<'a>,
61 },
62 Require {
63 specs: Vec<Context<'a, (&'a str, Identifier<'a>)>>,
64 },
65 Toolchain {
66 name: Identifier<'a>,
67 },
68 Godebug {
69 specs: Vec<Context<'a, (&'a str, &'a str)>>,
70 },
71 Replace {
72 specs: Vec<Context<'a, ReplaceSpec<'a>>>,
73 },
74 Exclude {
75 specs: Vec<Context<'a, (&'a str, Identifier<'a>)>>,
76 },
77 Retract {
78 specs: Vec<Context<'a, RetractSpec<'a>>>,
79 },
80}
81
82#[derive(Debug, Default, PartialEq, Eq)]
83pub struct Location {
84 pub line: u32,
85 pub offset: usize,
86}
87
88pub type Range = (Location, Location);
89
90#[derive(Debug, PartialEq, Eq)]
91pub struct Context<'a, T: 'a> {
92 pub range: Range,
93 pub comments: Vec<&'a str>,
94 pub value: T,
95}
96
97pub type GoMod<'a> = Vec<Context<'a, Directive<'a>>>;
98
99pub fn parse_gomod(text: &str) -> Result<GoMod, Err<Error<(u32, usize)>>> {
101 let (_, ret) = parser::parse_gomod(Span::new(text))
102 .map_err(|e| e.map_input(|i| (i.location_line(), i.location_offset())))?;
103 Ok(ret)
104}