Ajout de la gestion des variables dans le Bakefile et mise à jour des tests associés
This commit is contained in:
@@ -25,10 +25,21 @@ public class BakefileParser {
|
||||
*/
|
||||
private static final Pattern COMMAND_PATTERN = Pattern.compile("^\\s+(.+)$");
|
||||
|
||||
/**
|
||||
* Regex pour détecter les définitions de variables.
|
||||
* Format : "FLAGS = -ansi -pedantic"
|
||||
*/
|
||||
private static final Pattern VARIABLE_PATTERN = Pattern.compile("^(\\w+)\\s*=\\s*(.*)$");
|
||||
|
||||
/**
|
||||
* Première cible trouvée dans le fichier Bakefile.
|
||||
*/
|
||||
private static String firstTarget;
|
||||
|
||||
/**
|
||||
* Stocke les variables définies dans le Bakefile.
|
||||
*/
|
||||
private Map<String, String> variables = new HashMap<>();
|
||||
|
||||
|
||||
public BakefileParser(String filename) {
|
||||
@@ -39,53 +50,80 @@ public class BakefileParser {
|
||||
public List<Rule> parse() {
|
||||
List<Rule> rules = new ArrayList<>();
|
||||
Set<String> phonyTargets = new HashSet<>();
|
||||
|
||||
|
||||
if (!Files.exists(Paths.get(filename))) {
|
||||
System.out.println("*** No targets specified and no makefile found. Stop.");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
List<String> lines = Files.readAllLines(Paths.get(filename));
|
||||
String currentTarget = null;
|
||||
List<String> dependencies = new ArrayList<>();
|
||||
List<String> commands = new ArrayList<>();
|
||||
|
||||
|
||||
for (String line : lines) {
|
||||
Matcher varMatcher = VARIABLE_PATTERN.matcher(line);
|
||||
Matcher targetMatcher = TARGET_PATTERN.matcher(line);
|
||||
Matcher commandMatcher = COMMAND_PATTERN.matcher(line);
|
||||
|
||||
if (targetMatcher.matches()) {
|
||||
|
||||
if (varMatcher.matches()) {
|
||||
// Stocke la variable
|
||||
variables.put(varMatcher.group(1), varMatcher.group(2));
|
||||
} else if (targetMatcher.matches()) {
|
||||
if (firstTarget == null) {
|
||||
firstTarget = targetMatcher.group(1);
|
||||
}
|
||||
|
||||
// Sauvegarde de la règle précédente si elle existe
|
||||
|
||||
if (currentTarget != null) {
|
||||
rules.add(new Rule(currentTarget, dependencies, commands, phonyTargets.contains(currentTarget)));
|
||||
rules.add(new Rule(currentTarget, dependencies, replaceVariables(commands), phonyTargets.contains(currentTarget)));
|
||||
}
|
||||
|
||||
// Nouvelle cible détectée
|
||||
|
||||
currentTarget = targetMatcher.group(1);
|
||||
dependencies = new ArrayList<>(Arrays.asList(targetMatcher.group(2).trim().split("\\s+")));
|
||||
commands = new ArrayList<>();
|
||||
} else if (commandMatcher.matches()) {
|
||||
// Ligne de commande associée à la dernière cible trouvée
|
||||
commands.add(commandMatcher.group(1));
|
||||
}
|
||||
}
|
||||
|
||||
// Ajout de la dernière règle après la boucle
|
||||
|
||||
if (currentTarget != null) {
|
||||
rules.add(new Rule(currentTarget, dependencies, commands, phonyTargets.contains(currentTarget)));
|
||||
rules.add(new Rule(currentTarget, dependencies, replaceVariables(commands), phonyTargets.contains(currentTarget)));
|
||||
}
|
||||
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return rules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remplace les variables dans une liste de commandes.
|
||||
* Ex : "gcc $(FLAGS) -o main main.c" devient "gcc -ansi -pedantic -o main main.c"
|
||||
* @param commands Liste des commandes à modifier
|
||||
* @return Liste avec les variables remplacées
|
||||
*/
|
||||
private List<String> replaceVariables(List<String> commands) {
|
||||
List<String> resolvedCommands = new ArrayList<>();
|
||||
for (String command : commands) {
|
||||
boolean replaced;
|
||||
do {
|
||||
replaced = false;
|
||||
for (Map.Entry<String, String> entry : variables.entrySet()) {
|
||||
String key = "$(" + entry.getKey() + ")";
|
||||
if (command.contains(key)) {
|
||||
command = command.replace(key, entry.getValue());
|
||||
replaced = true;
|
||||
}
|
||||
}
|
||||
} while (replaced); // Continue tant qu'on remplace des variables
|
||||
resolvedCommands.add(command);
|
||||
}
|
||||
return resolvedCommands;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Permet de récupérer la première cible trouvée dans le fichier Bakefile.
|
||||
* @return La première cible trouvée
|
||||
|
Reference in New Issue
Block a user