/** TernaryLogic.java -- classes that describe a ternary logic system * @author Douglas Jones * @version mp2, 2017-02-21 * * This code borrows heavily from RoadNetwork.java distributed on 2017-02-10. * The goal in writing this code was to minimally but adequately meet the * requirements of the assignment while avoiding any creative additions to * the framework established by RoadNetwork.java other than bug fixes. * Where RoadNetwork.java contained support for features that were not * mentioned in the assignment (comments, for example), these were deleted. */ import java.util.LinkedList; import java.io.File; import java.io.FileNotFoundException; import java.util.Scanner; /** Utility package for error handling */ class Errors { private Errors(){}; // you may never instantiate this class /** Call this to warn of non fatal errors */ public static void warn( String message ) { System.err.println( "Warning: " + message ); } /** Call this to report fatal errors */ public static void fatal( String message ) { System.err.println( "Fatal error: " + message ); System.exit( -1 ); } } /** Wires link gates * @see Gate * @see Errors * @see TernaryLogic#findGate(String) */ class Wire { private final float delay; // time delay of this wire private final Gate destination; // where wire goes, or null private final Gate source; // source of wire, or null // Wire name is the source-destination names /** initializer scans and processes one wire definition */ public Wire( Scanner sc ) { // textual names of source and dest String srcName; String dstName; // read names of source and dest, guarantee they're not null if (sc.hasNext()) { srcName = sc.next(); } else { // error message comes from findGate() srcName = "????"; } if (sc.hasNext()) { dstName = sc.next(); } else { // error message comes from findGate() dstName = "????"; } // lookup and check names of source and dest source = TernaryLogic.findGate( srcName ); if (source == null) { Errors.warn( "Road '" + srcName + "' '" + dstName + "' source undefined." ); } destination = TernaryLogic.findGate( dstName ); if (destination == null) { Errors.warn( "Wire '" + srcName + "' '" + dstName + "' destination undefined." ); } // get delay of wire if (sc.hasNextFloat()) { delay = sc.nextFloat(); if (delay < 0.0f) { Errors.warn( "Wire '" + srcName + "' '" + dstName + "' '" + delay + "' has a negative delay." ); } } else { } else { Errors.warn( "Wire '" + srcName + "' '" + dstName + "' has no delay." ); delay = 99.999f; } sc.nextLine(); } /** output this wire in a format like that used for input */ public String toString() { String srcName; String dstName; if (source == null) { srcName = "???"; } else { srcName = source.name; } if (destination == null) { dstName = "???"; } else { dstName = destination.name; } return( "wire " + srcName + " " + dstName + " " + delay ); } } /** Gates are linked by wires * @see Wire * @see TernaryLogic#findGate(String) */ class Gate { private final LinkedList outgoing = new LinkedList (); // Bug: Does the gate need a list of incoming wires? public final String name; // the name of the gate public final String type; // the type of the gate public final int inputs; // the type of the gate public final float delay; // the type of the gate /** initializer scans and processes one gate definition */ public Gate( Scanner sc ) { // get and check gate name if (sc.hasNext()) { name = sc.next(); } else { Errors.warn( "gate has no name" ); name = "?????"; } if (TernaryLogic.findGate( name ) != null) { Errors.warn( "Gate '" + name + "' redefined." ); } // get and check gate type if (sc.hasNext()) { type = sc.next(); } else { // the warning for wrong type will come from below type = "????"; } if ( (!"min".equals( type ) ) // check for illegal name && (!"max".equals( type ) ) && (!"neg".equals( type ) ) && (!"istrue".equals( type ) ) && (!"isunknown".equals( type )) && (!"isfalse".equals( type ) ) ) { Errors.warn( "Gate '" + name + "' '" + type + "' has an illegal type." ); } // get and check gate input count if (sc.hasNextInt()) { inputs = sc.nextInt(); } else { inputs = 9999; Errors.warn( "Gate '" + name + "' '" + type + "' has no input count." ); } // get and check gate delay if (sc.hasNextFloat()) { delay = sc.nextFloat(); if (delay < 0.0f) { Errors.warn( "Gate '" + name + "' '" + type + "' '" + inputs + "' '" + delay + "' has a negative delay." ); } } else { delay = 99.999f; Errors.warn( "Gate '" + name + "' '" + type + "' '" + inputs + "' has no delay." ); } sc.nextLine(); } /** output this Intersection in a format like that used for input */ public String toString() { return( "gate " + name + " " + type + " " + inputs + " " + delay ); } } /** TernaryLogic -- main program that reads and writes a ternary logic system * @see Wire * @see Gate * @see Errors * @see #main */ public class TernaryLogic { // lists of roads and intersectins static LinkedList wires = new LinkedList (); static LinkedList gates = new LinkedList (); /** utility method to look up an gate by name * @param s is the name of the gate, a string * @return is the Gate object with that name */ public static Gate findGate( String s ) { for ( Gate g: gates ) { if (g.name.equals( s )) return g; } return null; } /** read a ternary logic system */ public static void initializeTernary( Scanner sc ) { while (sc.hasNext()) { // until we hit the end of the file String command = sc.next(); if ("gate".equals( command )) { gates.add( new Gate( sc ) ); } else if ("wire".equals( command )) { wires.add( new Wire( sc ) ); } else { Errors.warn( "Command '" + command + "' is not gate or wire" ); } } } /** write out a ternary logic system */ public static void writeTernary() { for ( Gate g: gates ) { System.out.println( g.toString() ); } for ( Wire w: wires ) { System.out.println( w.toString() ); } } /** main program that reads and writes a road network * @param args the command line arguments must hold one file name */ public static void main( String[] args ) { // verify that the argument exists. if (args.length < 1) { Errors.fatal( "Missing file name on command line" ); } else if (args.length > 1) { Errors.fatal( "Unexpected command line args" ); } else try { initializeTernary( new Scanner( new File( args[0] ) ) ); writeTernary(); } catch (FileNotFoundException e) { Errors.fatal( "Could not read '" + args[0] + "'" ); } } }