package net.jangaroo.jooc.util; import net.jangaroo.jooc.input.InputSource; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * A helper class for joo.flex that parses an "include" directive * and returns a Reader for the included file. * It can handle relative paths and line ranges. */ public final class IncludeEvaluator { private static final int BEGIN_INDEX = "include \"".length(); private static final Pattern FILENAME_WITH_LINE_RANGE_PATTERN = Pattern.compile("^(.*):([0-9]+),([0-9]+)$"); // utility class, do not instantiate private IncludeEvaluator() {} public static Reader createReader(String includeDirective, InputSource source) throws IOException { String filename = includeDirective.substring(BEGIN_INDEX, includeDirective.length() - 1); Matcher matcher = FILENAME_WITH_LINE_RANGE_PATTERN.matcher(filename); boolean hasLineRange = matcher.matches(); if (hasLineRange) { filename = matcher.group(1); } File file = new File(filename); InputStream in = null; if (!file.exists() && !file.isAbsolute()) { InputSource parent = source.getParent(); InputSource input = parent.getChild(filename); if (input == null) { throw new IOException("cannot find input file " + parent.getPath() + parent.getFileSeparatorChar() + filename); } in = input.getInputStream(); } if (in == null) { in = new FileInputStream(file); } Reader result = new InputStreamReader(in, "UTF-8"); if (hasLineRange) { int startLine = Integer.parseInt(matcher.group(2)) + 1; int endLine = Integer.parseInt(matcher.group(3)); result = new LineRangeReader(result, startLine, endLine); } return result; } }