Here's a line-processing algorithm that uses rescanning. void processLine(String line) { do { someReplacement = false for each macroName { replace all occurrences of macroName in line with macroExpansion if any replacements made someReplacement = true } } while (someReplacement) print line } You might not have seen it before but Java does have a do-while like shown above. It's commonly used when you want to make at least one pass through a loop but maybe not more. The line "for each macroName" above corresponds to the line "for (String macroName: macros.keySet())" in the lpphashmap.java example, but instead of printing the macro names and their expansions like the example does, you'll do replacements on the line instead.