aboutsummaryrefslogtreecommitdiff
path: root/src/makefile
diff options
context:
space:
mode:
Diffstat (limited to 'src/makefile')
-rw-r--r--src/makefile/macro.rs8
-rw-r--r--src/makefile/token.rs64
2 files changed, 47 insertions, 25 deletions
diff --git a/src/makefile/macro.rs b/src/makefile/macro.rs
index 43aff90..a6dcb74 100644
--- a/src/makefile/macro.rs
+++ b/src/makefile/macro.rs
@@ -103,6 +103,7 @@ impl<'parent, 'lookup> Set<'parent, 'lookup> {
match token {
Token::Text(t) => result.push_str(t),
Token::MacroExpansion { name, replacement } => {
+ let name = self.expand(name)?;
let internal_macro_names = &['@', '?', '<', '*'][..];
let internal_macro_suffices = &['D', 'F'][..];
let just_internal = name.len() == 1 && name.starts_with(internal_macro_names);
@@ -110,9 +111,9 @@ impl<'parent, 'lookup> Set<'parent, 'lookup> {
&& name.starts_with(internal_macro_names)
&& name.ends_with(internal_macro_suffices);
let macro_value = if just_internal || suffixed_internal {
- self.lookup_internal(name)?
+ self.lookup_internal(&name)?
} else {
- self.get(name).map_or_else(
+ self.get(&name).map_or_else(
|| {
log::warn!("undefined macro {}", name);
Ok(String::new())
@@ -139,8 +140,9 @@ impl<'parent, 'lookup> Set<'parent, 'lookup> {
}
#[cfg(feature = "full")]
Token::FunctionCall { name, args } => {
+ let name = self.expand(name)?;
let fn_result =
- functions::expand_call(name, args, self, Some(Rc::clone(&self.to_eval)))?;
+ functions::expand_call(&name, args, self, Some(Rc::clone(&self.to_eval)))?;
log::trace!("expanded {} into \"{}\"", token, &fn_result);
result.push_str(&fn_result);
}
diff --git a/src/makefile/token.rs b/src/makefile/token.rs
index 44d8c8b..b880700 100644
--- a/src/makefile/token.rs
+++ b/src/makefile/token.rs
@@ -4,7 +4,7 @@ use std::str::FromStr;
use eyre::WrapErr;
use nom::{
branch::alt,
- bytes::complete::{tag, take_till1, take_while1},
+ bytes::complete::{tag, take_till1},
character::complete::anychar,
combinator::{all_consuming, map, opt, verify},
error::{context, convert_error, ContextError, ParseError, VerboseError},
@@ -37,7 +37,7 @@ impl TokenString {
#[cfg(feature = "full")]
pub fn r#macro(name: impl Into<String>) -> Self {
Self(vec![Token::MacroExpansion {
- name: name.into(),
+ name: Self::text(name),
replacement: None,
}])
}
@@ -138,12 +138,12 @@ impl fmt::Display for TokenString {
pub enum Token {
Text(String),
MacroExpansion {
- name: String,
+ name: TokenString,
replacement: Option<(TokenString, TokenString)>,
},
#[cfg(feature = "full")]
FunctionCall {
- name: String,
+ name: TokenString,
args: Vec<TokenString>,
},
}
@@ -174,10 +174,10 @@ impl fmt::Display for Token {
}
}
-fn macro_function_name<'a, E: Err<'a>>(input: &'a str) -> IResult<&'a str, &'a str, E> {
- // POSIX says "periods, underscores, digits, and alphabetics from the portable character set"
- // one GNUism is a function with a - in the name
- take_while1(|c: char| c == '.' || c == '_' || c.is_alphanumeric() || c == '-')(input)
+fn macro_function_name<'a, E: Err<'a>>(
+ end: char,
+) -> impl FnMut(&'a str) -> IResult<&'a str, TokenString, E> + 'a {
+ tokens_but_not(vec![':', '#', '=', ' ', end])
}
fn macro_expansion_body<'a, E: Err<'a>>(
@@ -194,11 +194,8 @@ fn macro_expansion_body<'a, E: Err<'a>>(
context(
"macro_expansion_body",
map(
- pair(macro_function_name, opt(subst)),
- |(name, replacement)| Token::MacroExpansion {
- name: name.into(),
- replacement,
- },
+ pair(macro_function_name(end), opt(subst)),
+ |(name, replacement)| Token::MacroExpansion { name, replacement },
),
)
}
@@ -211,14 +208,11 @@ fn function_call_body<'a, E: Err<'a>>(
"function_call_body",
map(
separated_pair(
- macro_function_name,
+ macro_function_name(end),
space1,
separated_list1(pair(tag(","), space0), tokens_but_not(vec![',', end])),
),
- |(name, args)| Token::FunctionCall {
- name: name.into(),
- args,
- },
+ |(name, args)| Token::FunctionCall { name, args },
),
)
}
@@ -248,7 +242,7 @@ fn tiny_macro_expansion<'a, E: Err<'a>>(input: &'a str) -> IResult<&'a str, Toke
Token::Text("$".into())
} else {
Token::MacroExpansion {
- name: c.to_string(),
+ name: TokenString::text(c),
replacement: None,
}
}
@@ -335,7 +329,7 @@ mod test {
fn token_macro_expansion(name: impl Into<String>) -> Token {
Token::MacroExpansion {
- name: name.into(),
+ name: TokenString::text(name),
replacement: None,
}
}
@@ -346,7 +340,7 @@ mod test {
subst2: impl Into<TokenString>,
) -> Token {
Token::MacroExpansion {
- name: name.into(),
+ name: TokenString::text(name),
replacement: Some((subst1.into(), subst2.into())),
}
}
@@ -354,7 +348,7 @@ mod test {
#[cfg(feature = "full")]
fn token_function_call(name: impl Into<String>, args: Vec<impl Into<TokenString>>) -> Token {
Token::FunctionCall {
- name: name.into(),
+ name: TokenString::text(name),
args: args.into_iter().map(|x| x.into()).collect(),
}
}
@@ -468,4 +462,30 @@ mod test {
);
Ok(())
}
+
+ #[test]
+ fn triple_mega_deluxe_super_hell() -> R {
+ let text = "$($($(a)b)c)";
+ let tokens = tokenize(text)?;
+ assert_eq!(
+ tokens,
+ TokenString(vec![Token::MacroExpansion {
+ name: TokenString(vec![
+ Token::MacroExpansion {
+ name: TokenString(vec![
+ Token::MacroExpansion {
+ name: TokenString::text("a"),
+ replacement: None,
+ },
+ token_text("b"),
+ ]),
+ replacement: None,
+ },
+ token_text("c")
+ ]),
+ replacement: None,
+ }]),
+ );
+ Ok(())
+ }
}