yash_syntax/
source.rs

1// This file is part of yash, an extended POSIX shell.
2// Copyright (C) 2020 WATANABE Yuki
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program.  If not, see <https://www.gnu.org/licenses/>.
16
17//! Shell script source code
18//!
19//! This module re-exports source code related items from the
20//! [`yash-env`](yash_env) crate. It also defines the [`SourceChar`] struct
21//! representing a character with source description.
22
23use std::rc::Rc;
24
25#[doc(no_inline)]
26pub use yash_env::source::*;
27
28/// Creates an iterator of [source char](SourceChar)s from a string.
29///
30/// `index_offset` will be the index of the first source char's location.
31/// For each succeeding char, the index will be incremented by one.
32///
33/// ```
34/// # use yash_syntax::source::{Code, Source, source_chars};
35/// # use std::cell::RefCell;
36/// # use std::num::NonZeroU64;
37/// # use std::rc::Rc;
38/// let s = "abc";
39/// let code = Rc::new(Code {
40///     value: RefCell::new(s.to_string()),
41///     start_line_number: NonZeroU64::new(1).unwrap(),
42///     source: Rc::new(Source::Unknown),
43/// });
44/// let chars: Vec<_> = source_chars(s, &code, 10).collect();
45/// assert_eq!(chars[0].value, 'a');
46/// assert_eq!(chars[0].location.code, code);
47/// assert_eq!(chars[0].location.range, 10..11);
48/// assert_eq!(chars[1].value, 'b');
49/// assert_eq!(chars[1].location.code, code);
50/// assert_eq!(chars[1].location.range, 11..12);
51/// ```
52pub fn source_chars<'a>(
53    s: &'a str,
54    code: &'a Rc<Code>,
55    index_offset: usize,
56) -> impl Iterator<Item = SourceChar> + 'a {
57    s.chars().enumerate().map(move |(i, value)| SourceChar {
58        value,
59        location: Location {
60            code: Rc::clone(code),
61            range: index_offset + i..index_offset + i + 1,
62        },
63    })
64}
65
66/// Character with source description
67#[derive(Clone, Debug, Eq, PartialEq)]
68pub struct SourceChar {
69    /// Character value
70    pub value: char,
71    /// Location of this character in source code
72    pub location: Location,
73}