#!/usr/bin/env --split-string=${JDK_HOME}/bin/java @Makeshift/java_arguments @Makeshift/java_javac_arguments
import Breccia.parser.ParseError;
import Breccia.parser.plain.BrecciaCursor;
import Breccia.XML.translator.BrecciaXCursor;
import java.io.IOException;
import java.io.Reader;
import java.nio.file.Path;
import javax.xml.stream.XMLStreamException;
import static Breccia.parser.plain.Project.newSourceReader;
import static Breccia.XML.translator.BrecciaXCursor.EMPTY;
import static java.lang.System.err;
import static java.lang.System.out;
import static javax.xml.stream.XMLStreamConstants.*;
/** A shell command to smoke test the Breccia to X-Breccia translator.
*
* @see
* Usage instructions
*/
public final class SmokeTestCommand { // [AFN]
private SmokeTestCommand( Path sourceFile ) { this.sourceFile = sourceFile; }
public static void main( final String[] arguments ) throws IOException, XMLStreamException {
new SmokeTestCommand( Path.of( arguments[0] )).execute(); }
//// P r i v a t e ////////////////////////////////////////////////////////////////////////////////////
private void execute() throws IOException, XMLStreamException {
try( final Reader sourceReader = newSourceReader( sourceFile );
final BrecciaXCursor sourceXCursor = new BrecciaXCursor() ) {
final BrecciaCursor sourceCursor = new BrecciaCursor();
sourceCursor.source( sourceReader );
sourceXCursor.source( sourceCursor );
for( final BrecciaXCursor in = sourceXCursor;; ) {
switch( in.getEventType() ) {
case CHARACTERS -> {}
case EMPTY -> out.println( "Empty source file" );
case END_DOCUMENT -> {}
case END_ELEMENT -> {
indent();
out.print( in.getLocalName() );
out.println();
--indent; }
case START_DOCUMENT -> {}
case START_ELEMENT -> {
indent();
out.print( in.getLocalName() );
out.println();
++indent; }
default -> throw new IllegalStateException(); } /* The event type being
either `HALT`, or one not actually emitted by `BrecciaXCursor` at the time
of coding. For the event types emitted, see the `assert` statement
and comment at the foot of method `BrecciaXCursor.next`. */
if( !in.hasNext() ) break;
try { in.next(); }
catch( final XMLStreamException x ) { throw (ParseError)(x.getCause()); }}}
catch( final ParseError x ) {
err.print( sourceFile );
err.print( ':' );
err.print( x.lineNumber );
err.print( ": " );
err.println( x ); }}
private int indent;
private void indent() { for( int i = 0; i < indent; ++i ) out.print( " " ); }
private final Path sourceFile; }
// NOTE
// ────
// AFN Atypical file naming is allowed here. ‘The compiler does not enforce the optional restriction
// defined at the end of JLS §7.6, that a type in a named package should exist in a file whose
// name is composed from the type name followed by the .java extension.’
//
//
//
// No longer, however, does this allowance extend to the package name. While in JDK releases
// prior to 22 “the launcher's source-file mode was permissive about which package, if any,
// was declared”, current releases enforce a correspondence between the declared package name
// and the file path. Failing this, the launcher aborts with “end of path to source file
// does not match its package name”.