Skip to content
This repository has been archived by the owner on Jun 3, 2021. It is now read-only.

Commit

Permalink
Clean up top-level API
Browse files Browse the repository at this point in the history
  • Loading branch information
jyn514 authored and Joshua Nelson committed May 13, 2020
1 parent daf0726 commit cbe3948
Show file tree
Hide file tree
Showing 6 changed files with 207 additions and 187 deletions.
4 changes: 1 addition & 3 deletions src/data/lex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -427,9 +427,7 @@ pub(crate) mod test {
}
/// Create a new preprocessor with `s` as the input, but without a trailing newline
pub(crate) fn cpp_no_newline(s: &str) -> PreProcessor {
let mut files: Files = Default::default();
let id = files.add("<test suite>", String::new().into());
PreProcessorBuilder::new(s, id, Box::leak(Box::new(files))).build()
PreProcessorBuilder::new(s).build()
}

#[test]
Expand Down
78 changes: 42 additions & 36 deletions src/lex/cpp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ use std::convert::TryFrom;
use std::path::{Path, PathBuf};
use std::rc::Rc;

use codespan::FileId;

use super::{Lexer, Token};
use crate::arch::TARGET;
use crate::data::error::CppError;
Expand All @@ -20,24 +18,18 @@ use crate::Files;
///
/// Here is the example for `PreProcessor::new()` using the builder:
/// ```
/// use rcc::{Files, PreProcessorBuilder, Source};
/// use rcc::PreProcessorBuilder;
///
/// let mut files = Files::new();
/// let code = String::from("int main(void) { char *hello = \"hi\"; }\n").into();
/// let src = Source { path: "example.c".into(), code: std::rc::Rc::clone(&code) };
/// let file = files.add("example.c", src);
/// let cpp = PreProcessorBuilder::new(code, file, &mut files).build();
/// let cpp = PreProcessorBuilder::new("int main(void) { char *hello = \"hi\"; }\n").filename("example.c").build();
/// for token in cpp {
/// assert!(token.is_ok());
/// }
/// ```
pub struct PreProcessorBuilder<'a> {
/// The buffer for the starting file
buf: Rc<str>,
/// The starting file
file: FileId,
/// All known files, including files which have already been read.
files: &'a mut Files,
/// The name of the file
filename: PathBuf,
/// Whether to print each token before replacement
debug: bool,
/// The paths to search for `#include`d files
Expand All @@ -47,20 +39,19 @@ pub struct PreProcessorBuilder<'a> {
}

impl<'a> PreProcessorBuilder<'a> {
pub fn new<S: Into<Rc<str>>>(
buf: S,
file: FileId,
files: &'a mut Files,
) -> PreProcessorBuilder<'a> {
pub fn new<S: Into<Rc<str>>>(buf: S) -> PreProcessorBuilder<'a> {
PreProcessorBuilder {
debug: false,
files,
file,
filename: PathBuf::default(),
buf: buf.into(),
search_path: Vec::new(),
definitions: HashMap::new(),
}
}
pub fn filename<P: Into<PathBuf>>(mut self, name: P) -> Self {
self.filename = name.into();
self
}
pub fn debug(mut self, yes: bool) -> Self {
self.debug = yes;
self
Expand All @@ -75,12 +66,11 @@ impl<'a> PreProcessorBuilder<'a> {
}
pub fn build(self) -> PreProcessor<'a> {
PreProcessor::new(
self.file,
self.buf,
self.filename,
self.debug,
self.search_path,
self.definitions,
self.files,
)
}
}
Expand All @@ -104,13 +94,9 @@ impl<'a> PreProcessorBuilder<'a> {
/// Examples:
///
/// ```
/// use rcc::{Files, PreProcessor, Source};
/// use rcc::PreProcessor;
///
/// let mut files = Files::new();
/// let code = String::from("int main(void) { char *hello = \"hi\"; }\n").into();
/// let src = Source { path: "example.c".into(), code: std::rc::Rc::clone(&code) };
/// let file = files.add("example.c", src);
/// let cpp = PreProcessor::new(file, code, false, vec![], Default::default(), &mut files);
/// let cpp = PreProcessor::new("int main(void) { char *hello = \"hi\"; }\n", "example.c", false, vec![], Default::default());
/// for token in cpp {
/// assert!(token.is_ok());
/// }
Expand All @@ -122,7 +108,7 @@ pub struct PreProcessor<'a> {
/// Each lexer represents a separate source file that is currently being processed.
includes: Vec<Lexer>,
/// All known files, including files which have already been read.
files: &'a mut Files,
files: Files,
/// Note that this is a simple HashMap and not a Scope, because
/// the preprocessor has no concept of scope other than `undef`
definitions: HashMap<InternedStr, Definition>,
Expand Down Expand Up @@ -385,18 +371,12 @@ impl<'a> PreProcessor<'a> {
/// but will never delete a file.
///
/// The `debug` parameter specifies whether to print out tokens before replacement.
pub fn new<
'files: 'a,
'search: 'a,
I: IntoIterator<Item = Cow<'search, Path>>,
S: Into<Rc<str>>,
>(
file: FileId,
pub fn new<'search: 'a, I: IntoIterator<Item = Cow<'search, Path>>, S: Into<Rc<str>>>(
chars: S,
filename: impl Into<std::ffi::OsString>,
debug: bool,
user_search_path: I,
user_definitions: HashMap<InternedStr, Definition>,
files: &'files mut Files,
) -> Self {
let system_path = format!(
"{}-{}-{}",
Expand Down Expand Up @@ -424,6 +404,16 @@ impl<'a> PreProcessor<'a> {
Path::new("/usr/include").into(),
];
search_path.extend(user_search_path.into_iter());

let mut files = Files::new();
let chars = chars.into();
let filename = filename.into();
let source = crate::Source {
code: Rc::clone(&chars),
path: filename.clone().into(),
};
let file = files.add(filename, source);

Self {
first_lexer: Lexer::new(file, chars, debug),
includes: Default::default(),
Expand Down Expand Up @@ -459,6 +449,22 @@ impl<'a> PreProcessor<'a> {
std::mem::take(&mut self.error_handler.warnings)
}

/// Return a `Location` representing the end of the first file.
pub fn eof(&self) -> Location {
let lex = &self.first_lexer;
Location {
span: (lex.chars.len() as u32..lex.chars.len() as u32).into(),
file: lex.location.file,
}
}

/// Return all files loaded by the preprocessor, consuming it in the process.
///
/// Files can be loaded by C source using `#include` directives.
pub fn into_files(self) -> Files {
self.files
}

/* internal functions */
/// Return all tokens from the current position until the end of the current line.
///
Expand Down
Loading

0 comments on commit cbe3948

Please sign in to comment.