import java.io.File;
import java.io.IOException;
import java.util.Scanner;
import java.util.regex.Pattern;
import java.util.NoSuchElementException;
import java.util.List;
import java.util.ArrayList;

public class FullLiteralFinder2 {
    // regex for string literal, or other things that can
    // contain a " character
    // group 1: the entire string literal
    // group 2: string literal without the double-quotes
    // gorup 4: beginning of a multi-line comment
    private static Pattern litSearch = Pattern.compile(
        "(\"(([^\"\\\\]|\\\\.)*)\")" // string literal
        + "|(/\\*)" // beginning of a multi-line comment
        + "|(//.*)" // single-line comment
        + "|('([^\\\\]|\\\\.)')" // char literal
        );

    // regex for the end of a multi-line comment
    private static Pattern comEnd = Pattern.compile(
        "([^*]|\\*(?!/))*\\*/");

    static List<String> getLiterals(String fname) throws IOException {
        Scanner scan = new Scanner(new File(fname));
        List<String> literals = new ArrayList<>();

        while (true) {
            if (scan.findInLine(litSearch) == null) {
                // no more interesting things on this line, so move to the next line
                try { scan.nextLine(); }
                catch (NoSuchElementException e) {
                    // this exception means the end-of-file (EOF) was reached
                    break;
                }
                continue;
            }

            if (scan.match().group(1) != null) {
                // string literal found
                // replace escape sequences with their meaning
                String contents = scan.match().group(2)
                    .replaceAll("\\\\n", "\n")
                    .replaceAll("\\\\t", "\t")
                    .replaceAll("\\\\(.)", "$1");
                literals.add(contents);
            }
            else if (scan.match().group(4) != null) {
                // beginning of multiline comment found
                // keep scanning until we find the end of it
                while (scan.findInLine(comEnd) == null) {
                    scan.nextLine();
                }
            }
        }

        return literals;
    }

    public static void main(String[] args) throws IOException {
        String fname = args[0];
        System.out.format("literals in %s:\n", fname);
        for (String literal : getLiterals(fname)) {
            System.out.format("  |%s|\n", literal);
        }
    }
}
