package fr.monlouyan.bakefile; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; public class BakefileParser { /** * Nom du fichier Bakefile à parser (donc Bakefile...). */ private String filename; /** * Regex pour détecter les targets et leurs dépendances. * Format : "nom : dépendance1 dépendance2" */ private static final Pattern TARGET_PATTERN = Pattern.compile("^(\\S+)\\s*:\\s*(.*)$"); /** * Regex pour détecter les lignes de commande associées à une target. * Format : " gcc -o program program.c" (ligne indentée) */ private static final Pattern COMMAND_PATTERN = Pattern.compile("^\\s+(.+)$"); /** * Première cible trouvée dans le fichier Bakefile. */ private static String firstTarget; public BakefileParser(String filename) { this.filename = filename; firstTarget = null; } public List parse() { List rules = new ArrayList<>(); Set 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 lines = Files.readAllLines(Paths.get(filename)); String currentTarget = null; List dependencies = new ArrayList<>(); List commands = new ArrayList<>(); for (String line : lines) { Matcher targetMatcher = TARGET_PATTERN.matcher(line); Matcher commandMatcher = COMMAND_PATTERN.matcher(line); 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))); } // 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))); } } catch (IOException e) { e.printStackTrace(); } return rules; } /** * Permet de récupérer la première cible trouvée dans le fichier Bakefile. * @return La première cible trouvée */ public static String getFirstTarget() { return firstTarget; } }