Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion make/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
// SPDX-License-Identifier: MIT
//

use std::collections::{BTreeMap, BTreeSet};
use std::collections::{BTreeMap, BTreeSet, HashMap};

/// Represents the configuration of the make utility
#[derive(Debug, Clone, PartialEq, Eq)]
Expand Down Expand Up @@ -36,6 +36,7 @@ pub struct Config {
pub precious: bool,

pub rules: BTreeMap<String, BTreeSet<String>>,
pub macros: HashMap<String, String>,
}

impl Default for Config {
Expand Down Expand Up @@ -113,6 +114,7 @@ impl Default for Config {
.collect::<BTreeSet<String>>(),
)
]),
macros: HashMap::new()
}
}
}
Expand Down
14 changes: 9 additions & 5 deletions make/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use std::{
time::SystemTime,
};

use parser::{Makefile, VariableDefinition};
use parser::Makefile;

use crate::special_target::InferenceTarget;
use config::Config;
Expand All @@ -38,7 +38,6 @@ const DEFAULT_SHELL: &str = "/bin/sh";
///
/// The only way to create a Make is from a Makefile and a Config.
pub struct Make {
macros: Vec<VariableDefinition>,
rules: Vec<Rule>,
default_rule: Option<Rule>, // .DEFAULT
pub config: Config,
Expand Down Expand Up @@ -111,7 +110,7 @@ impl Make {
for prerequisite in &newer_prerequisites {
self.build_target(prerequisite)?;
}
rule.run(&self.config, &self.macros, target, up_to_date)?;
rule.run(&self.config, target, up_to_date)?;

Ok(true)
}
Expand Down Expand Up @@ -183,11 +182,17 @@ impl Make {
impl TryFrom<(Makefile, Config)> for Make {
type Error = ErrorCode;

fn try_from((makefile, config): (Makefile, Config)) -> Result<Self, Self::Error> {
fn try_from((makefile, mut config): (Makefile, Config)) -> Result<Self, Self::Error> {
let mut rules = vec![];
let mut special_rules = vec![];
let mut inference_rules = vec![];

for macr in makefile.macros() {
config
.macros
.insert(macr.name().unwrap(), macr.raw_value().unwrap());
}

for rule in makefile.rules() {
let rule = Rule::from(rule);
let Some(target) = rule.targets().next() else {
Expand All @@ -205,7 +210,6 @@ impl TryFrom<(Makefile, Config)> for Make {

let mut make = Self {
rules,
macros: makefile.variable_definitions().collect(),
default_rule: None,
config,
};
Expand Down
10 changes: 9 additions & 1 deletion make/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
//

use core::str::FromStr;
use std::collections::{BTreeMap, BTreeSet};
use std::collections::{BTreeMap, BTreeSet, HashMap};
use std::ffi::OsString;
use std::io::Read;
use std::path::{Path, PathBuf};
Expand Down Expand Up @@ -179,6 +179,10 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
keep_going,
mut targets,
} = Args::parse();
let target_list = targets
.iter()
.filter_map(|x| x.clone().into_string().ok())
.fold(String::new(), |acc, x| acc + " " + &x);

let mut status_code = 0;

Expand All @@ -199,6 +203,10 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
print,
precious: false,
terminate,
macros: HashMap::from([
(String::from("MAKECMDGOALS"), target_list),
(String::from("MAKE"), env::args().next().unwrap()),
]),
..Default::default()
};

Expand Down
10 changes: 3 additions & 7 deletions make/src/parser/lex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,6 @@ impl<'a> Lexer<'a> {
}
}

fn is_whitespace(c: char) -> bool {
c == ' ' || c == '\t'
}

fn is_newline(c: char) -> bool {
c == '\n' || c == '\r'
}
Expand Down Expand Up @@ -64,6 +60,9 @@ impl<'a> Lexer<'a> {
/// - `None` if the input is exhausted.
///
fn next_token(&mut self) -> Option<(SyntaxKind, String)> {
while matches!(self.input.peek(), Some(' ')) {
self.input.next();
}
if let Some(&c) = self.input.peek() {
match (c, self.line_type) {
('\t', None) => {
Expand Down Expand Up @@ -96,9 +95,6 @@ impl<'a> Lexer<'a> {
Some((SyntaxKind::TEXT, self.read_while(|c| !Self::is_newline(c))))
}
LineType::Other => match c {
c if Self::is_whitespace(c) => {
Some((SyntaxKind::WHITESPACE, self.read_while(Self::is_whitespace)))
}
c if Self::is_valid_identifier_char(c) => {
let ident = self.read_while(Self::is_valid_identifier_char);

Expand Down
3 changes: 2 additions & 1 deletion make/src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub mod lex;
pub mod parse;
pub mod preprocessor;

pub use parse::{Identifier, Makefile, Rule, VariableDefinition};
pub use parse::{Identifier, MacroDef, Makefile, Rule};

/// Let's start with defining all kinds of tokens and
/// composite nodes.
Expand Down Expand Up @@ -71,6 +71,7 @@ pub enum SyntaxKind {
RECIPE,
VARIABLE,
EXPR,
MACRODEF,
MACRO,
}

Expand Down
47 changes: 33 additions & 14 deletions make/src/parser/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ impl rowan::Language for Lang {
use rowan::GreenNode;

use super::SyntaxKind;
use crate::parser::preprocessor::preprocess;
/// You can construct GreenNodes by hand, but a builder
/// is helpful for top-down parsers: it maintains a stack
/// of currently in-progress nodes
Expand Down Expand Up @@ -144,7 +143,7 @@ pub fn parse(text: &str) -> Result<Parsed, ParseError> {
self.builder.start_node(RECIPE.into());
self.expect(INDENT);
self.expect(TEXT);
self.expect(NEWLINE);
self.try_expect(NEWLINE);
self.builder.finish_node();
}

Expand All @@ -156,18 +155,30 @@ pub fn parse(text: &str) -> Result<Parsed, ParseError> {
self.expect(IDENTIFIER);
self.skip_ws();
}
self.expect(NEWLINE);
self.try_expect(NEWLINE);
self.builder.token(IDENTIFIER.into(), "variables.mk");
dbg!(&self.builder);
self.builder.finish_node();
}

fn parse_macro_defintion(&mut self) {
self.builder.start_node(MACRODEF.into());
self.try_expect(EXPORT);
self.expect(IDENTIFIER);
self.expect(EQUALS);
self.parse_expr();
self.builder.finish_node();
}

fn parse_rule(&mut self) {
self.builder.start_node(RULE.into());
self.skip_ws();
self.try_expect(EXPORT);
self.skip_ws();
self.expect(IDENTIFIER);
let is_pattern = self.try_expect(PERCENT);
if !is_pattern {
self.expect(IDENTIFIER);
}
self.skip_ws();
if self.tokens.pop() == Some((COLON, ":".to_string())) {
self.builder.token(COLON.into(), ":");
Expand All @@ -176,7 +187,7 @@ pub fn parse(text: &str) -> Result<Parsed, ParseError> {
}
self.skip_ws();
self.parse_expr();
self.expect(NEWLINE);
self.try_expect(NEWLINE);
loop {
match self.current() {
Some(INDENT) => {
Expand All @@ -197,7 +208,10 @@ pub fn parse(text: &str) -> Result<Parsed, ParseError> {
fn parse(mut self) -> Parse {
self.builder.start_node(ROOT.into());
loop {
match self.find(|&&(k, _)| k == COLON || k == NEWLINE || k == INCLUDE) {
match self
.find(|&&(k, _)| k == COLON || k == NEWLINE || k == INCLUDE || k == EQUALS)
{
Some((EQUALS, "=")) => self.parse_macro_defintion(),
Some((COLON, ":")) => {
self.parse_rule();
}
Expand Down Expand Up @@ -347,12 +361,16 @@ macro_rules! ast_node {
};
}

ast_node!(Macro, MACRO);
ast_node!(MacroDef, MACRODEF);
ast_node!(Makefile, ROOT);
ast_node!(Rule, RULE);
ast_node!(Identifier, IDENTIFIER);
ast_node!(VariableDefinition, VARIABLE);

impl VariableDefinition {
impl Macro {}
impl MacroDef {}

impl MacroDef {
pub fn name(&self) -> Option<String> {
self.syntax().children_with_tokens().find_map(|it| {
it.as_token().and_then(|it| {
Expand Down Expand Up @@ -403,15 +421,17 @@ impl Makefile {
self.syntax().children().filter_map(Rule::cast)
}

pub fn macros(&self) -> impl Iterator<Item = MacroDef> {
self.syntax().children().filter_map(MacroDef::cast)
}

pub fn rules_by_target<'a>(&'a self, target: &'a str) -> impl Iterator<Item = Rule> + 'a {
self.rules()
.filter(move |rule| rule.targets().any(|t| t == target))
}

pub fn variable_definitions(&self) -> impl Iterator<Item = VariableDefinition> {
self.syntax()
.children()
.filter_map(VariableDefinition::cast)
pub fn variable_definitions(&self) -> impl Iterator<Item = MacroDef> {
self.syntax().children().filter_map(MacroDef::cast)
}

pub fn add_rule(&mut self, target: &str) -> Rule {
Expand Down Expand Up @@ -530,7 +550,6 @@ impl FromStr for Makefile {
type Err = ParseError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
let processed = preprocess(s).map_err(|e| ParseError(vec![e.to_string()]))?;
parse(&processed).map(|node| node.root())
parse(s).map(|node| node.root())
}
}
Loading