/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * JFlex 1.8.2                                                             *
 * Copyright (C) 1998-2018  Gerwin Klein <lsf@jflex.de>                    *
 * All rights reserved.                                                    *
 *                                                                         *
 * License: BSD                                                            *
 *                                                                         *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package jflex.skeleton;

import static java.nio.charset.StandardCharsets.UTF_8;
import static jflex.logging.Out.NL;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import jflex.exceptions.GeneratorException;
import jflex.l10n.ErrorMessages;
import jflex.logging.Out;

This class stores the skeleton of generated scanners.

The skeleton consists of several parts that can be emitted to a file. Usually there is a portion of generated code (produced in class Emitter) between every two parts of skeleton code.

There is a static part (the skeleton code) and state based iterator part to this class. The iterator part is used to emit consecutive skeleton sections to some PrintWriter.

Author:Gerwin Klein
See Also:
Version:JFlex 1.8.2
/** * This class stores the skeleton of generated scanners. * * <p>The skeleton consists of several parts that can be emitted to a file. Usually there is a * portion of generated code (produced in class Emitter) between every two parts of skeleton code. * * <p>There is a static part (the skeleton code) and state based iterator part to this class. The * iterator part is used to emit consecutive skeleton sections to some {@code PrintWriter}. * * @see jflex.generator.Emitter * @author Gerwin Klein * @version JFlex 1.8.2 */
public class Skeleton {
location of default skeleton
/** location of default skeleton */
private static final String DEFAULT_LOC = "jflex/skeleton.default";
expected number of sections in the skeleton file
/** expected number of sections in the skeleton file */
private static final int size = 21;
The skeleton
/** The skeleton */
public static String[] line; static { readDefault(); } // the state based, iterator part of Skeleton:
The current part of the skeleton (an index of nextStop[])
/** The current part of the skeleton (an index of nextStop[]) */
private int pos;
The writer to write the skeleton-parts to
/** The writer to write the skeleton-parts to */
private final PrintWriter out;
Creates a new skeleton (iterator) instance.
Params:
  • out – the writer to write the skeleton-parts to
/** * Creates a new skeleton (iterator) instance. * * @param out the writer to write the skeleton-parts to */
public Skeleton(PrintWriter out) { this.out = out; }
Emits the next part of the skeleton
/** Emits the next part of the skeleton */
public void emitNext() { out.print(line[pos++]); }
Make the skeleton private.

Replaces all occurrences of " public " in the skeleton with " private ".

/** * Make the skeleton private. * * <p>Replaces all occurrences of " public " in the skeleton with " private ". */
public static void makePrivate() { for (int i = 0; i < line.length; i++) { line[i] = replace(" public ", " private ", line[i]); } }
Reads an external skeleton file for later use with this class.
Params:
  • skeletonFile – the file to read (must be != null and readable)
/** * Reads an external skeleton file for later use with this class. * * @param skeletonFile the file to read (must be != null and readable) */
public static void readSkelFile(File skeletonFile) { if (skeletonFile == null) throw new IllegalArgumentException("Skeleton file must not be null"); if (!skeletonFile.isFile() || !skeletonFile.canRead()) { Out.error(ErrorMessages.CANNOT_READ_SKEL, skeletonFile.toString()); throw new GeneratorException(); } Out.println(ErrorMessages.READING_SKEL, skeletonFile.toString()); try (BufferedReader reader = Files.newBufferedReader(Paths.get(skeletonFile.toString()), UTF_8)) { readSkel(reader); } catch (IOException e) { Out.error(ErrorMessages.SKEL_IO_ERROR); throw new GeneratorException(e); } }
Reads an external skeleton file from a BufferedReader.
Params:
  • reader – the reader to read from (must be != null)
Throws:
/** * Reads an external skeleton file from a BufferedReader. * * @param reader the reader to read from (must be != null) * @throws java.io.IOException if an IO error occurs * @throws GeneratorException if the number of skeleton sections does not match */
public static void readSkel(BufferedReader reader) throws IOException { List<String> lines = new ArrayList<>(); StringBuilder section = new StringBuilder(); String ln; while ((ln = reader.readLine()) != null) { if (ln.startsWith("---")) { // $NON-NLS-1$ lines.add(section.toString()); section.setLength(0); } else { section.append(ln); section.append(NL); } } if (section.length() > 0) lines.add(section.toString()); if (lines.size() != size) { Out.error(ErrorMessages.WRONG_SKELETON); throw new GeneratorException(); } line = new String[size]; for (int i = 0; i < size; i++) line[i] = lines.get(i); }
Replaces a with b in c.
Params:
  • a – the String to be replaced
  • b – the replacement
  • c – the String in which to replace a by b
Returns:a String object with a replaced by b in c
/** * Replaces a with b in c. * * @param a the String to be replaced * @param b the replacement * @param c the String in which to replace a by b * @return a String object with a replaced by b in c */
public static String replace(String a, String b, String c) { StringBuilder result = new StringBuilder(c.length()); int i = 0; int j = c.indexOf(a); while (j >= i) { result.append(c.substring(i, j)); result.append(b); i = j + a.length(); j = c.indexOf(a, i); } result.append(c.substring(i, c.length())); return result.toString(); }
(Re)load the default skeleton. Looks in the current system class path.
/** (Re)load the default skeleton. Looks in the current system class path. */
public static void readDefault() { ClassLoader l = Skeleton.class.getClassLoader(); URL url; /* Try to load from same class loader as this class. * Should work, but does not on OS/2 JDK 1.1.8 (see bug 1065521). * Use system class loader in this case. */ if (l != null) { url = l.getResource(DEFAULT_LOC); } else { url = ClassLoader.getSystemResource(DEFAULT_LOC); } if (url == null) { Out.error(ErrorMessages.SKEL_IO_ERROR_DEFAULT); throw new GeneratorException(); } try (BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream(), UTF_8))) { readSkel(reader); } catch (IOException e) { Out.error(ErrorMessages.SKEL_IO_ERROR_DEFAULT); throw new GeneratorException(e); } } }