<commit_before>package net.xprova.verilogparser;

import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.misc.Interval;

import net.xprova.netlist.GateLibrary;
import net.xprova.netlist.Module;
import net.xprova.netlist.Net;
import net.xprova.netlist.Netlist;
import net.xprova.netlist.PinConnection;
import net.xprova.netlist.PinDirection;
import net.xprova.netlist.Port;
import net.xprova.verilogparser.Verilog2001Parser.Continuous_assignContext;
import net.xprova.verilogparser.Verilog2001Parser.DescriptionContext;
import net.xprova.verilogparser.Verilog2001Parser.ExpressionContext;
import net.xprova.verilogparser.Verilog2001Parser.Inout_declarationContext;
import net.xprova.verilogparser.Verilog2001Parser.Input_declarationContext;
import net.xprova.verilogparser.Verilog2001Parser.List_of_port_connectionsContext;
import net.xprova.verilogparser.Verilog2001Parser.List_of_portsContext;
import net.xprova.verilogparser.Verilog2001Parser.Module_declarationContext;
import net.xprova.verilogparser.Verilog2001Parser.Module_instanceContext;
import net.xprova.verilogparser.Verilog2001Parser.Module_instantiationContext;
import net.xprova.verilogparser.Verilog2001Parser.Module_itemContext;
import net.xprova.verilogparser.Verilog2001Parser.Module_or_generate_itemContext;
import net.xprova.verilogparser.Verilog2001Parser.Module_or_generate_item_declarationContext;
import net.xprova.verilogparser.Verilog2001Parser.Named_port_connectionContext;
import net.xprova.verilogparser.Verilog2001Parser.Net_assignmentContext;
import net.xprova.verilogparser.Verilog2001Parser.Net_declarationContext;
import net.xprova.verilogparser.Verilog2001Parser.Net_identifierContext;
import net.xprova.verilogparser.Verilog2001Parser.Net_typeContext;
import net.xprova.verilogparser.Verilog2001Parser.Ordered_port_connectionContext;
import net.xprova.verilogparser.Verilog2001Parser.Output_declarationContext;
import net.xprova.verilogparser.Verilog2001Parser.PortContext;
import net.xprova.verilogparser.Verilog2001Parser.Port_declarationContext;
import net.xprova.verilogparser.Verilog2001Parser.Port_identifierContext;
import net.xprova.verilogparser.Verilog2001Parser.PrimaryContext;
import net.xprova.verilogparser.Verilog2001Parser.RangeContext;
import net.xprova.verilogparser.Verilog2001Parser.Source_textContext;
import net.xprova.verilogparser.Verilog2001Parser.TermContext;

/**
 *
 * Module
 *
 */
public class VerilogParser {

	// class members

	private static CommonTokenStream tokenStream;

	private static GateLibrary library1;

	// error messages

	private final static String ERR_MSG_1 = "port <%s> not declared in module header";
	private final static String ERR_MSG_2 = "could not parse port list";
	private final static String ERR_MSG_3 = "direction of port <%s> unspecified";
	private final static String ERR_MSG_4 = "unsupported grammar";
	private final static String ERR_MSG_5 = "port <%s> declared more than once in module header";
	private final static String ERR_MSG_6 = "unsupported net declaration grammar";
	private final static String ERR_MSG_7 = "Unsupported grammar for bit range";
	private final static String ERR_MSG_8 = "net redefinition";
	private final static String ERR_MSG_9 = "declaration mismatch between port <%s> [%d:%d] and wire <%s> [%d:%d]";

	private final static String ERR_MSG_10 = "implicit declaratin of array net";
	private final static String ERR_MSG_12 = "gate instantiation is not supported";
	private final static String ERR_MSG_13 = "unsupported module connection";

	private final static String ERR_MSG_15 = "redefinition of module instance <%s>";
	private final static String ERR_MSG_16 = "module %s does not exist in library";
	private final static String ERR_MSG_17 = "non-scalar net <%s> must be explicitly declared";

	// exception generation and handling

	private static void fail(String filename, String errMsg, Module_itemContext itemCon)
			throws UnsupportedGrammerException {

		Interval int1 = itemCon.getSourceInterval(); // get token interval

		Token firstToken = tokenStream.get(int1.a);

		int lineNum = firstToken.getLine(); // get line of first token

		// Determining j, first token in int1 which occurs at a different line

		int j;

		for (j = int1.a; j < int1.b; j++) {

			if (tokenStream.get(j).getLine() != lineNum)
				break;
		}

		// form a string from tokens 1 through j-1

		String tokenStr = tokenStream.getText(new Interval(int1.a, j));

		System.err.printf("Parser error (%s:%d): %s\n", filename, lineNum, tokenStr);

		System.err.println(errMsg);

		throw new UnsupportedGrammerException("");

	}

	private static void fail(String errMsg) throws UnsupportedGrammerException {

		throw new UnsupportedGrammerException(errMsg);

	}

	// parsing

	public static ArrayList<Netlist> parseFile(String verilogFile) throws Exception {

		// This form of the method is used for parsing library files.
		// Modules in library files may not instantiate any modules within them;
		// then can only contain port declarations, for example:
		// module NOT (y, a); input a; output y; endmodule

		return parseFile(verilogFile, new GateLibrary());

	}

	public static ArrayList<Netlist> parseFile(String verilogFile, GateLibrary library) throws Exception {

		FileInputStream stream1 = new FileInputStream(verilogFile);

		return parse(verilogFile, new ANTLRInputStream(stream1), library);

	}

	public static ArrayList<Netlist> parseString(String str) throws Exception {

		// This form of the method is used for parsing library files.
		// Modules in library files may not instantiate any modules within them;
		// then can only contain port declarations, for example:
		// module NOT (y, a); input a; output y; endmodule

		return parseString(str, new GateLibrary());

	}

	public static ArrayList<Netlist> parseString(String str, GateLibrary library) throws Exception {

		return parse("STRING", new ANTLRInputStream(str), library);

	}

	private static ArrayList<Netlist> parse(String filename, ANTLRInputStream antlr, GateLibrary library1)
			throws Exception {

		// ANTLR parsing

		Verilog2001Lexer lexer1 = new Verilog2001Lexer(antlr);

		CommonTokenStream tokenStream = new CommonTokenStream(lexer1);

		Verilog2001Parser parser1 = new Verilog2001Parser(tokenStream);

		Source_textContext source = parser1.source_text();

		List<DescriptionContext> modules = source.description();

		int nModules = modules.size();

		ArrayList<Netlist> netlistArr = new ArrayList<Netlist>();

		for (int j = 0; j < nModules; j++) {

			Module_declarationContext module = modules.get(j).module_declaration();

			VerilogParser.tokenStream = tokenStream;

			VerilogParser.library1 = library1;

			Netlist netlist = new Netlist();

			netlist.name = module.module_identifier().getText();

			List_of_portsContext portList = module.list_of_ports();

			if (portList == null) {

				fail(ERR_MSG_4);
			}

			ArrayList<String> ports = new ArrayList<String>();

			for (int i = 0; i < portList.port().size(); i++) {

				ports.add(portList.port(i).getText());

			}

			// Initialize member variables

			netlist.ports = new HashMap<String, Port>();

			netlist.nets = new HashMap<String, Net>();

			netlist.modules = new HashMap<String, Module>();

			netlist.orderedPorts = ports;

			List<Module_itemContext> x = module.module_item();

			// parse ports

			parsePortList(module, netlist);

			// main parsing loop:

			// initially goes through the module items adding them to either
			// netDefs, modDefs, assignDefs or throwing a parsing exception

			ArrayList<Module_itemContext> netDefs = new ArrayList<Module_itemContext>();

			ArrayList<Module_itemContext> modDefs = new ArrayList<Module_itemContext>();

			ArrayList<Module_itemContext> assignDefs = new ArrayList<Module_itemContext>();

			for (int i = 0; i < x.size(); i++) {

				Module_itemContext itemCon = x.get(i);

				if (itemCon.port_declaration() != null) {

					// port declaration

					parsePortDeclaration(filename, itemCon, netlist);

					continue;
				}

				Module_or_generate_itemContext modItem = itemCon.module_or_generate_item();

				if (modItem != null) {

					if (modItem.gate_instantiation() != null) {

						fail(filename, ERR_MSG_12, itemCon);

						continue;
					}

					if (modItem.module_instantiation() != null) {

						modDefs.add(itemCon);

						continue;
					}

					Module_or_generate_item_declarationContext modItem2 = modItem.module_or_generate_item_declaration();

					if (modItem2 != null) {

						Net_declarationContext netDec = modItem2.net_declaration();

						if (netDec != null) {

							// net declaration

							Net_typeContext netType = netDec.net_type();

							if (netType.getText().equals("wire")) {

								// net definition

								netDefs.add(itemCon);

								continue;
							}

						} else {

							fail(filename, ERR_MSG_6, itemCon);
						}
					}

					Continuous_assignContext conAssignItem = modItem.continuous_assign();

					if (conAssignItem != null) {

						List<Net_assignmentContext> assignList = conAssignItem.list_of_net_assignments()
								.net_assignment();

						for (Net_assignmentContext conAssign : assignList) {

							String lval = conAssign.net_lvalue().getText();
							String rval = conAssign.expression().getText();

							// boolean isEscapedL = lval.startsWith("\\");
							boolean isEscapedR = rval.startsWith("\\");

							boolean looksArrL = lval.contains(":");
							boolean looksArrR = rval.contains(":");

							boolean looksConcatL = lval.contains("{");
							boolean nestedConcatR = (rval.indexOf("{") != rval.lastIndexOf("{"));

							// check lval

							if (looksArrL || looksConcatL)
								fail(filename, ERR_MSG_4, itemCon);

							// check rval

							if ((looksArrR || nestedConcatR) && !isEscapedR)
								fail(filename, ERR_MSG_4, itemCon);

							// item can be parsed:

							assignDefs.add(itemCon);

						}

						continue;

					}

				}

				// Unsupported grammar

				fail(filename, ERR_MSG_4, itemCon);

			}

			// now process netDefs then modDefs

			// order is important: nets must be populated before processing
			// modules

			for (Module_itemContext entry : netDefs) {

				parseNetDeclaration(filename, entry, netlist);
			}

			for (Module_itemContext entry : modDefs) {

				parseModuleInstantiation(filename, entry, netlist);
			}

			for (Module_itemContext entry : assignDefs) {

				parseAssignStatement(filename, entry, netlist);
			}

			checkAll(netlist);

			netlistArr.add(netlist);

		}

		return netlistArr;

	}

	private static void parsePortList(Module_declarationContext module, Netlist netlist)
			throws UnsupportedGrammerException {

		if (module.list_of_ports() == null) {

			fail(ERR_MSG_2);

		}

		List<PortContext> portList = module.list_of_ports().port();

		if (portList.size() == 1 && "".equals(portList.get(0).getText())) {
			System.out.println("warning: empty port list");

			return;
		}

		for (int i = 0; i < portList.size(); i++) {

			String name = portList.get(i).getText();

			Port p = new Port(name, PinDirection.UNKONWN);

			if (netlist.ports.containsKey(name)) {

				String emsg = String.format(ERR_MSG_5, name);

				fail(emsg);
			}

			netlist.ports.put(name, p);

			netlist.nets.put(name, p);

		}

	}

	private static void parseAssignStatement(String filename, Module_itemContext itemCon, Netlist netlist)
			throws Exception {

		List<Net_assignmentContext> assignList = itemCon.module_or_generate_item().continuous_assign()
				.list_of_net_assignments().net_assignment();

		for (Net_assignmentContext conAssign : assignList) {

			String lval = conAssign.net_lvalue().getText();
			String rval = conAssign.expression().getText();

			boolean isConcatR = rval.contains("{");

			if (isConcatR) {

				int k1 = rval.indexOf("{");
				int k2 = rval.indexOf("}");

				String netNamesStr = rval.substring(k1 + 1, k2);

				String[] netNames = netNamesStr.split(",");

				int bitIndex = 0;

				for (String netName : netNames) {

					String wireModID = "WIRE_NG_INTERNAL_u" + netlist.modules.size();

					Module m = new Module(wireModID, "WIRE_NG_INTERNAL");

					netlist.modules.put(wireModID, m);

					// segment below in this for loop is from
					// processModulePinConnection (tokens == 1)

					m.connections.put("IN", new PinConnection(netName, 0, PinDirection.IN));
					m.connections.put("OUT", new PinConnection(lval, bitIndex, PinDirection.OUT));

					Net net = netlist.nets.get(netName);

					if (net == null) {

						// implicit net declaration

						netlist.nets.put(netName, new Net(netName));

					} else {

						// check if bit 0 is in net range

						if (!netlist.nets.get(netName).inRange(0)) {

							String msg1_a = "net <%s> does not have bit <%d>";

							String msg2 = String.format(msg1_a, netName, 0);

							fail(filename, msg2, itemCon);
						}

					}

					bitIndex += 1;

				}

			} else {

				String wireModID = "WIRE_NG_INTERNAL_u" + netlist.modules.size();

				Module m = new Module(wireModID, "WIRE_NG_INTERNAL");

				netlist.modules.put(wireModID, m);

				ParserRuleContext zpL = conAssign.net_lvalue();
				ParserRuleContext zpR = conAssign.expression();

				Port pIn = new Port("IN", PinDirection.IN);
				Port pOut = new Port("OUT", PinDirection.OUT);

				processModulePinConnection(filename, m, zpL, lval, itemCon, pOut, netlist);
				processModulePinConnection(filename, m, zpR, rval, itemCon, pIn, netlist);

			}

		}

	}

	private static void parseModuleInstantiation(String filename, Module_itemContext itemCon, Netlist netlist)
			throws Exception {

		Module_or_generate_itemContext modItem = itemCon.module_or_generate_item();

		Module_instantiationContext modIns = modItem.module_instantiation();

		String id = modIns.module_identifier().getText();

		List<Module_instanceContext> instances = modIns.module_instance();

		for (int j = 0; j < instances.size(); j++) {

			Module_instanceContext i = instances.get(j);

			Module m = new Module();

			m.type = id;

			m.id = i.name_of_instance().getText();

			ArrayList<Port> modulePorts = library1.get(id);

			if (modulePorts == null) {

				String msg2 = String.format(ERR_MSG_16, id);

				fail(filename, msg2, itemCon);

			}

			List_of_port_connectionsContext conList = i.list_of_port_connections();

			List<Ordered_port_connectionContext> orderedCons = conList.ordered_port_connection();

			List<Named_port_connectionContext> namedCons = conList.named_port_connection();

			boolean ordered = orderedCons.size() > 0;

			int conCount = ordered ? orderedCons.size() : namedCons.size();

			if (conCount > modulePorts.size()) {

				String strE = String.format(
						"module instantiation contains %d ports while only %d are defined in library", conCount,
						modulePorts.size());

				fail(filename, strE, itemCon);

			}

			for (int k = 0; k < conCount; k++) {

				ExpressionContext expr;

				expr = ordered ? orderedCons.get(k).expression() : namedCons.get(k).expression();

				List<TermContext> termList = expr.term();

				if (termList.size() != 1) {

					fail(filename, ERR_MSG_4, itemCon);
				}

				TermContext z = termList.get(0);

				PrimaryContext zp = z.primary();

				String port_con = "";

				if (zp.hierarchical_identifier() != null) {

					port_con = zp.hierarchical_identifier().getText();

				} else if (zp.number() != null) {

					port_con = zp.number().getText();

				} else {

					fail("ERR_MSG_2");
				}

				String port_id = ordered ? modulePorts.get(k).id : namedCons.get(k).port_identifier().getText();

				// PinDirection dir = library1.getPort(id, port_id).direction;

				Port port = library1.getPort(id, port_id);

				processModulePinConnection(filename, m, zp, port_con, itemCon, port, netlist);

			}

			if (netlist.modules.containsKey(m.id)) {

				String msg = String.format(ERR_MSG_15, m.id);

				fail(filename, msg, itemCon);
			}

			netlist.modules.put(m.id, m);

		}

	}

	private static void parseNetDeclaration(String filename, Module_itemContext itemCon, Netlist netlist)
			throws UnsupportedGrammerException {

		Module_or_generate_itemContext modItem = itemCon.module_or_generate_item();

		Module_or_generate_item_declarationContext modItem2 = modItem.module_or_generate_item_declaration();

		Net_declarationContext netDec = modItem2.net_declaration();

		RangeContext r = netDec.range();

		int start = 0, end = 0;

		if (r != null) {

			ExpressionContext expMSB = r.msb_constant_expression().constant_expression().expression();

			ExpressionContext expLSB = r.lsb_constant_expression().constant_expression().expression();

			try {

				start = Integer.parseInt(expMSB.getText());

				end = Integer.parseInt(expLSB.getText());

			} catch (Exception e) {

				fail(filename, ERR_MSG_7, itemCon);

			}

		}

		List<Net_identifierContext> list = netDec.list_of_net_identifiers().net_identifier();

		for (int j = 0; j < list.size(); j++) {

			String netName = list.get(j).getText();

			if (netlist.nets.get(netName) != null) {

				fail(filename, ERR_MSG_8, itemCon);

			} else {

				Net net = new Net(netName);

				net.start = start;

				net.end = end;

				netlist.nets.put(netName, net);

			}

		}

	}

	private static void parsePortDeclaration(String filename, Module_itemContext itemCon, Netlist netlist)
			throws UnsupportedGrammerException {

		Port_declarationContext portDec = itemCon.port_declaration();

		Input_declarationContext inp = portDec.input_declaration();

		Output_declarationContext outp = portDec.output_declaration();

		Inout_declarationContext inout = portDec.inout_declaration();

		List<Port_identifierContext> portList = null;

		RangeContext r = null;

		PinDirection direction = PinDirection.UNKONWN;

		if (inp != null) {

			portList = inp.list_of_port_identifiers().port_identifier();

			direction = PinDirection.IN;

			r = inp.range();

		} else if (outp != null) {

			portList = outp.list_of_port_identifiers().port_identifier();

			direction = PinDirection.OUT;

			r = outp.range();

		} else if (inout != null) {

			portList = inout.list_of_port_identifiers().port_identifier();

			direction = PinDirection.INOUT;

			r = inout.range();

			// fail(ERR_MSG_14, itemCon);

		}

		for (int j = 0; j < portList.size(); j++) {

			Port_identifierContext portIdent = portList.get(j);

			String portName = portIdent.getText();

			// now need to lookup this port in ArrayList ports

			Port p = netlist.ports.get(portName);

			if (p == null) {

				// port wasn't declared in module header

				String str = String.format(ERR_MSG_1, portName);

				fail(filename, str, itemCon);

			}

			p.direction = direction;

			if (r != null) {

				ExpressionContext expMSB = r.msb_constant_expression().constant_expression().expression();

				ExpressionContext expLSB = r.lsb_constant_expression().constant_expression().expression();

				try {

					p.start = Integer.parseInt(expMSB.getText());

					p.end = Integer.parseInt(expLSB.getText());

				} catch (Exception e) {

					fail(filename, ERR_MSG_7, itemCon);

				}

			}

		}
	}

	private static void processModulePinConnection(String filename, Module m, ParserRuleContext zp, String port_con,
			Module_itemContext itemCon, Port port, Netlist netlist) throws UnsupportedGrammerException {

		// this function processes a single port connection of a given module
		// instantiation

		// this function does the following:
		// - adds a PinConnection to the `connections` set of Module `m`
		// - create any single-bit nets that the port connection references, and
		// adds them to netlist.nets

		// inputs:

		// filename : quoted when throwing parsing exceptions
		// m : Module object
		// zp : holds the tokens for the net to which the port is connected
		// port_id : id of module port to be connected
		// port_con : net to be connected to module
		// itemCon : context of module instantiation (needed when throwing
		// Exceptions)
		// dir : direction of pin

		int tokens = zp.stop.getTokenIndex() - zp.start.getTokenIndex() + 1;

		if (tokens == 1) {

			// identifier, e.g. x

			Net net = netlist.nets.get(port_con);

			if (net == null)
				fail(filename, ERR_MSG_10, itemCon);

			for (int bit : port.getBits()) {
<commit_msg>Re-enable implicit net declaration for non-array port connections<commit_after>package net.xprova.verilogparser;

import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.misc.Interval;

import net.xprova.netlist.GateLibrary;
import net.xprova.netlist.Module;
import net.xprova.netlist.Net;
import net.xprova.netlist.Netlist;
import net.xprova.netlist.PinConnection;
import net.xprova.netlist.PinDirection;
import net.xprova.netlist.Port;
import net.xprova.verilogparser.Verilog2001Parser.Continuous_assignContext;
import net.xprova.verilogparser.Verilog2001Parser.DescriptionContext;
import net.xprova.verilogparser.Verilog2001Parser.ExpressionContext;
import net.xprova.verilogparser.Verilog2001Parser.Inout_declarationContext;
import net.xprova.verilogparser.Verilog2001Parser.Input_declarationContext;
import net.xprova.verilogparser.Verilog2001Parser.List_of_port_connectionsContext;
import net.xprova.verilogparser.Verilog2001Parser.List_of_portsContext;
import net.xprova.verilogparser.Verilog2001Parser.Module_declarationContext;
import net.xprova.verilogparser.Verilog2001Parser.Module_instanceContext;
import net.xprova.verilogparser.Verilog2001Parser.Module_instantiationContext;
import net.xprova.verilogparser.Verilog2001Parser.Module_itemContext;
import net.xprova.verilogparser.Verilog2001Parser.Module_or_generate_itemContext;
import net.xprova.verilogparser.Verilog2001Parser.Module_or_generate_item_declarationContext;
import net.xprova.verilogparser.Verilog2001Parser.Named_port_connectionContext;
import net.xprova.verilogparser.Verilog2001Parser.Net_assignmentContext;
import net.xprova.verilogparser.Verilog2001Parser.Net_declarationContext;
import net.xprova.verilogparser.Verilog2001Parser.Net_identifierContext;
import net.xprova.verilogparser.Verilog2001Parser.Net_typeContext;
import net.xprova.verilogparser.Verilog2001Parser.Ordered_port_connectionContext;
import net.xprova.verilogparser.Verilog2001Parser.Output_declarationContext;
import net.xprova.verilogparser.Verilog2001Parser.PortContext;
import net.xprova.verilogparser.Verilog2001Parser.Port_declarationContext;
import net.xprova.verilogparser.Verilog2001Parser.Port_identifierContext;
import net.xprova.verilogparser.Verilog2001Parser.PrimaryContext;
import net.xprova.verilogparser.Verilog2001Parser.RangeContext;
import net.xprova.verilogparser.Verilog2001Parser.Source_textContext;
import net.xprova.verilogparser.Verilog2001Parser.TermContext;

/**
 *
 * Module
 *
 */
public class VerilogParser {

	// class members

	private static CommonTokenStream tokenStream;

	private static GateLibrary library1;

	// error messages

	private final static String ERR_MSG_1 = "port <%s> not declared in module header";
	private final static String ERR_MSG_2 = "could not parse port list";
	private final static String ERR_MSG_3 = "direction of port <%s> unspecified";
	private final static String ERR_MSG_4 = "unsupported grammar";
	private final static String ERR_MSG_5 = "port <%s> declared more than once in module header";
	private final static String ERR_MSG_6 = "unsupported net declaration grammar";
	private final static String ERR_MSG_7 = "Unsupported grammar for bit range";
	private final static String ERR_MSG_8 = "net redefinition";
	private final static String ERR_MSG_9 = "declaration mismatch between port <%s> [%d:%d] and wire <%s> [%d:%d]";

	private final static String ERR_MSG_10 = "implicit declaratin of array net";
	private final static String ERR_MSG_12 = "gate instantiation is not supported";
	private final static String ERR_MSG_13 = "unsupported module connection";

	private final static String ERR_MSG_15 = "redefinition of module instance <%s>";
	private final static String ERR_MSG_16 = "module %s does not exist in library";
	private final static String ERR_MSG_17 = "non-scalar net <%s> must be explicitly declared";

	// exception generation and handling

	private static void fail(String filename, String errMsg, Module_itemContext itemCon)
			throws UnsupportedGrammerException {

		Interval int1 = itemCon.getSourceInterval(); // get token interval

		Token firstToken = tokenStream.get(int1.a);

		int lineNum = firstToken.getLine(); // get line of first token

		// Determining j, first token in int1 which occurs at a different line

		int j;

		for (j = int1.a; j < int1.b; j++) {

			if (tokenStream.get(j).getLine() != lineNum)
				break;
		}

		// form a string from tokens 1 through j-1

		String tokenStr = tokenStream.getText(new Interval(int1.a, j));

		System.err.printf("Parser error (%s:%d): %s\n", filename, lineNum, tokenStr);

		System.err.println(errMsg);

		throw new UnsupportedGrammerException("");

	}

	private static void fail(String errMsg) throws UnsupportedGrammerException {

		throw new UnsupportedGrammerException(errMsg);

	}

	// parsing

	public static ArrayList<Netlist> parseFile(String verilogFile) throws Exception {

		// This form of the method is used for parsing library files.
		// Modules in library files may not instantiate any modules within them;
		// then can only contain port declarations, for example:
		// module NOT (y, a); input a; output y; endmodule

		return parseFile(verilogFile, new GateLibrary());

	}

	public static ArrayList<Netlist> parseFile(String verilogFile, GateLibrary library) throws Exception {

		FileInputStream stream1 = new FileInputStream(verilogFile);

		return parse(verilogFile, new ANTLRInputStream(stream1), library);

	}

	public static ArrayList<Netlist> parseString(String str) throws Exception {

		// This form of the method is used for parsing library files.
		// Modules in library files may not instantiate any modules within them;
		// then can only contain port declarations, for example:
		// module NOT (y, a); input a; output y; endmodule

		return parseString(str, new GateLibrary());

	}

	public static ArrayList<Netlist> parseString(String str, GateLibrary library) throws Exception {

		return parse("STRING", new ANTLRInputStream(str), library);

	}

	private static ArrayList<Netlist> parse(String filename, ANTLRInputStream antlr, GateLibrary library1)
			throws Exception {

		// ANTLR parsing

		Verilog2001Lexer lexer1 = new Verilog2001Lexer(antlr);

		CommonTokenStream tokenStream = new CommonTokenStream(lexer1);

		Verilog2001Parser parser1 = new Verilog2001Parser(tokenStream);

		Source_textContext source = parser1.source_text();

		List<DescriptionContext> modules = source.description();

		int nModules = modules.size();

		ArrayList<Netlist> netlistArr = new ArrayList<Netlist>();

		for (int j = 0; j < nModules; j++) {

			Module_declarationContext module = modules.get(j).module_declaration();

			VerilogParser.tokenStream = tokenStream;

			VerilogParser.library1 = library1;

			Netlist netlist = new Netlist();

			netlist.name = module.module_identifier().getText();

			List_of_portsContext portList = module.list_of_ports();

			if (portList == null) {

				fail(ERR_MSG_4);
			}

			ArrayList<String> ports = new ArrayList<String>();

			for (int i = 0; i < portList.port().size(); i++) {

				ports.add(portList.port(i).getText());

			}

			// Initialize member variables

			netlist.ports = new HashMap<String, Port>();

			netlist.nets = new HashMap<String, Net>();

			netlist.modules = new HashMap<String, Module>();

			netlist.orderedPorts = ports;

			List<Module_itemContext> x = module.module_item();

			// parse ports

			parsePortList(module, netlist);

			// main parsing loop:

			// initially goes through the module items adding them to either
			// netDefs, modDefs, assignDefs or throwing a parsing exception

			ArrayList<Module_itemContext> netDefs = new ArrayList<Module_itemContext>();

			ArrayList<Module_itemContext> modDefs = new ArrayList<Module_itemContext>();

			ArrayList<Module_itemContext> assignDefs = new ArrayList<Module_itemContext>();

			for (int i = 0; i < x.size(); i++) {

				Module_itemContext itemCon = x.get(i);

				if (itemCon.port_declaration() != null) {

					// port declaration

					parsePortDeclaration(filename, itemCon, netlist);

					continue;
				}

				Module_or_generate_itemContext modItem = itemCon.module_or_generate_item();

				if (modItem != null) {

					if (modItem.gate_instantiation() != null) {

						fail(filename, ERR_MSG_12, itemCon);

						continue;
					}

					if (modItem.module_instantiation() != null) {

						modDefs.add(itemCon);

						continue;
					}

					Module_or_generate_item_declarationContext modItem2 = modItem.module_or_generate_item_declaration();

					if (modItem2 != null) {

						Net_declarationContext netDec = modItem2.net_declaration();

						if (netDec != null) {

							// net declaration

							Net_typeContext netType = netDec.net_type();

							if (netType.getText().equals("wire")) {

								// net definition

								netDefs.add(itemCon);

								continue;
							}

						} else {

							fail(filename, ERR_MSG_6, itemCon);
						}
					}

					Continuous_assignContext conAssignItem = modItem.continuous_assign();

					if (conAssignItem != null) {

						List<Net_assignmentContext> assignList = conAssignItem.list_of_net_assignments()
								.net_assignment();

						for (Net_assignmentContext conAssign : assignList) {

							String lval = conAssign.net_lvalue().getText();
							String rval = conAssign.expression().getText();

							// boolean isEscapedL = lval.startsWith("\\");
							boolean isEscapedR = rval.startsWith("\\");

							boolean looksArrL = lval.contains(":");
							boolean looksArrR = rval.contains(":");

							boolean looksConcatL = lval.contains("{");
							boolean nestedConcatR = (rval.indexOf("{") != rval.lastIndexOf("{"));

							// check lval

							if (looksArrL || looksConcatL)
								fail(filename, ERR_MSG_4, itemCon);

							// check rval

							if ((looksArrR || nestedConcatR) && !isEscapedR)
								fail(filename, ERR_MSG_4, itemCon);

							// item can be parsed:

							assignDefs.add(itemCon);

						}

						continue;

					}

				}

				// Unsupported grammar

				fail(filename, ERR_MSG_4, itemCon);

			}

			// now process netDefs then modDefs

			// order is important: nets must be populated before processing
			// modules

			for (Module_itemContext entry : netDefs) {

				parseNetDeclaration(filename, entry, netlist);
			}

			for (Module_itemContext entry : modDefs) {

				parseModuleInstantiation(filename, entry, netlist);
			}

			for (Module_itemContext entry : assignDefs) {

				parseAssignStatement(filename, entry, netlist);
			}

			checkAll(netlist);

			netlistArr.add(netlist);

		}

		return netlistArr;

	}

	private static void parsePortList(Module_declarationContext module, Netlist netlist)
			throws UnsupportedGrammerException {

		if (module.list_of_ports() == null) {

			fail(ERR_MSG_2);

		}

		List<PortContext> portList = module.list_of_ports().port();

		if (portList.size() == 1 && "".equals(portList.get(0).getText())) {
			System.out.println("warning: empty port list");

			return;
		}

		for (int i = 0; i < portList.size(); i++) {

			String name = portList.get(i).getText();

			Port p = new Port(name, PinDirection.UNKONWN);

			if (netlist.ports.containsKey(name)) {

				String emsg = String.format(ERR_MSG_5, name);

				fail(emsg);
			}

			netlist.ports.put(name, p);

			netlist.nets.put(name, p);

		}

	}

	private static void parseAssignStatement(String filename, Module_itemContext itemCon, Netlist netlist)
			throws Exception {

		List<Net_assignmentContext> assignList = itemCon.module_or_generate_item().continuous_assign()
				.list_of_net_assignments().net_assignment();

		for (Net_assignmentContext conAssign : assignList) {

			String lval = conAssign.net_lvalue().getText();
			String rval = conAssign.expression().getText();

			boolean isConcatR = rval.contains("{");

			if (isConcatR) {

				int k1 = rval.indexOf("{");
				int k2 = rval.indexOf("}");

				String netNamesStr = rval.substring(k1 + 1, k2);

				String[] netNames = netNamesStr.split(",");

				int bitIndex = 0;

				for (String netName : netNames) {

					String wireModID = "WIRE_NG_INTERNAL_u" + netlist.modules.size();

					Module m = new Module(wireModID, "WIRE_NG_INTERNAL");

					netlist.modules.put(wireModID, m);

					// segment below in this for loop is from
					// processModulePinConnection (tokens == 1)

					m.connections.put("IN", new PinConnection(netName, 0, PinDirection.IN));
					m.connections.put("OUT", new PinConnection(lval, bitIndex, PinDirection.OUT));

					Net net = netlist.nets.get(netName);

					if (net == null) {

						// implicit net declaration

						netlist.nets.put(netName, new Net(netName));

					} else {

						// check if bit 0 is in net range

						if (!netlist.nets.get(netName).inRange(0)) {

							String msg1_a = "net <%s> does not have bit <%d>";

							String msg2 = String.format(msg1_a, netName, 0);

							fail(filename, msg2, itemCon);
						}

					}

					bitIndex += 1;

				}

			} else {

				String wireModID = "WIRE_NG_INTERNAL_u" + netlist.modules.size();

				Module m = new Module(wireModID, "WIRE_NG_INTERNAL");

				netlist.modules.put(wireModID, m);

				ParserRuleContext zpL = conAssign.net_lvalue();
				ParserRuleContext zpR = conAssign.expression();

				Port pIn = new Port("IN", PinDirection.IN);
				Port pOut = new Port("OUT", PinDirection.OUT);

				processModulePinConnection(filename, m, zpL, lval, itemCon, pOut, netlist);
				processModulePinConnection(filename, m, zpR, rval, itemCon, pIn, netlist);

			}

		}

	}

	private static void parseModuleInstantiation(String filename, Module_itemContext itemCon, Netlist netlist)
			throws Exception {

		Module_or_generate_itemContext modItem = itemCon.module_or_generate_item();

		Module_instantiationContext modIns = modItem.module_instantiation();

		String id = modIns.module_identifier().getText();

		List<Module_instanceContext> instances = modIns.module_instance();

		for (int j = 0; j < instances.size(); j++) {

			Module_instanceContext i = instances.get(j);

			Module m = new Module();

			m.type = id;

			m.id = i.name_of_instance().getText();

			ArrayList<Port> modulePorts = library1.get(id);

			if (modulePorts == null) {

				String msg2 = String.format(ERR_MSG_16, id);

				fail(filename, msg2, itemCon);

			}

			List_of_port_connectionsContext conList = i.list_of_port_connections();

			List<Ordered_port_connectionContext> orderedCons = conList.ordered_port_connection();

			List<Named_port_connectionContext> namedCons = conList.named_port_connection();

			boolean ordered = orderedCons.size() > 0;

			int conCount = ordered ? orderedCons.size() : namedCons.size();

			if (conCount > modulePorts.size()) {

				String strE = String.format(
						"module instantiation contains %d ports while only %d are defined in library", conCount,
						modulePorts.size());

				fail(filename, strE, itemCon);

			}

			for (int k = 0; k < conCount; k++) {

				ExpressionContext expr;

				expr = ordered ? orderedCons.get(k).expression() : namedCons.get(k).expression();

				List<TermContext> termList = expr.term();

				if (termList.size() != 1) {

					fail(filename, ERR_MSG_4, itemCon);
				}

				TermContext z = termList.get(0);

				PrimaryContext zp = z.primary();

				String port_con = "";

				if (zp.hierarchical_identifier() != null) {

					port_con = zp.hierarchical_identifier().getText();

				} else if (zp.number() != null) {

					port_con = zp.number().getText();

				} else {

					fail("ERR_MSG_2");
				}

				String port_id = ordered ? modulePorts.get(k).id : namedCons.get(k).port_identifier().getText();

				// PinDirection dir = library1.getPort(id, port_id).direction;

				Port port = library1.getPort(id, port_id);

				processModulePinConnection(filename, m, zp, port_con, itemCon, port, netlist);

			}

			if (netlist.modules.containsKey(m.id)) {

				String msg = String.format(ERR_MSG_15, m.id);

				fail(filename, msg, itemCon);
			}

			netlist.modules.put(m.id, m);

		}

	}

	private static void parseNetDeclaration(String filename, Module_itemContext itemCon, Netlist netlist)
			throws UnsupportedGrammerException {

		Module_or_generate_itemContext modItem = itemCon.module_or_generate_item();

		Module_or_generate_item_declarationContext modItem2 = modItem.module_or_generate_item_declaration();

		Net_declarationContext netDec = modItem2.net_declaration();

		RangeContext r = netDec.range();

		int start = 0, end = 0;

		if (r != null) {

			ExpressionContext expMSB = r.msb_constant_expression().constant_expression().expression();

			ExpressionContext expLSB = r.lsb_constant_expression().constant_expression().expression();

			try {

				start = Integer.parseInt(expMSB.getText());

				end = Integer.parseInt(expLSB.getText());

			} catch (Exception e) {

				fail(filename, ERR_MSG_7, itemCon);

			}

		}

		List<Net_identifierContext> list = netDec.list_of_net_identifiers().net_identifier();

		for (int j = 0; j < list.size(); j++) {

			String netName = list.get(j).getText();

			if (netlist.nets.get(netName) != null) {

				fail(filename, ERR_MSG_8, itemCon);

			} else {

				Net net = new Net(netName);

				net.start = start;

				net.end = end;

				netlist.nets.put(netName, net);

			}

		}

	}

	private static void parsePortDeclaration(String filename, Module_itemContext itemCon, Netlist netlist)
			throws UnsupportedGrammerException {

		Port_declarationContext portDec = itemCon.port_declaration();

		Input_declarationContext inp = portDec.input_declaration();

		Output_declarationContext outp = portDec.output_declaration();

		Inout_declarationContext inout = portDec.inout_declaration();

		List<Port_identifierContext> portList = null;

		RangeContext r = null;

		PinDirection direction = PinDirection.UNKONWN;

		if (inp != null) {

			portList = inp.list_of_port_identifiers().port_identifier();

			direction = PinDirection.IN;

			r = inp.range();

		} else if (outp != null) {

			portList = outp.list_of_port_identifiers().port_identifier();

			direction = PinDirection.OUT;

			r = outp.range();

		} else if (inout != null) {

			portList = inout.list_of_port_identifiers().port_identifier();

			direction = PinDirection.INOUT;

			r = inout.range();

			// fail(ERR_MSG_14, itemCon);

		}

		for (int j = 0; j < portList.size(); j++) {

			Port_identifierContext portIdent = portList.get(j);

			String portName = portIdent.getText();

			// now need to lookup this port in ArrayList ports

			Port p = netlist.ports.get(portName);

			if (p == null) {

				// port wasn't declared in module header

				String str = String.format(ERR_MSG_1, portName);

				fail(filename, str, itemCon);

			}

			p.direction = direction;

			if (r != null) {

				ExpressionContext expMSB = r.msb_constant_expression().constant_expression().expression();

				ExpressionContext expLSB = r.lsb_constant_expression().constant_expression().expression();

				try {

					p.start = Integer.parseInt(expMSB.getText());

					p.end = Integer.parseInt(expLSB.getText());

				} catch (Exception e) {

					fail(filename, ERR_MSG_7, itemCon);

				}

			}

		}
	}

	private static void processModulePinConnection(String filename, Module m, ParserRuleContext zp, String port_con,
			Module_itemContext itemCon, Port port, Netlist netlist) throws UnsupportedGrammerException {

		// this function does the following:
		// - adds a PinConnection to the `connections` set of Module `m`
		// - create any single-bit nets that the port connection references, and
		// adds them to netlist.nets

		// inputs:

		// filename : quoted when throwing parsing exceptions
		// m : Module object
		// zp : holds the tokens for the net to which the port is connected
		// port_id : id of module port to be connected
		// port_con : net to be connected to module
		// itemCon : context of module instantiation (needed when throwing
		// Exceptions)
		// dir : direction of pin

		int tokens = zp.stop.getTokenIndex() - zp.start.getTokenIndex() + 1;

		if (tokens == 1) {

			// identifier, e.g. x

			Net net = netlist.nets.get(port_con);

			if (net == null) {

				// implicit net declaration

				if (port.getCount() > 1) {

					// implicit net declaration with array ports is not
					// supported atm

					fail(filename, ERR_MSG_10, itemCon);

				} else {

					netlist.nets.put(port_con, new Net(port_con));

				}
			}

			for (int bit : port.getBits()) {

{'fraction_non_alphanumeric': 0.10921916808562393, 'fraction_numerical': 0.011408416443687668, 'mean_word_length': 3.917583732057416, 'pattern_counts': {'":': 4, '<': 99, '<?xml version=': 0, '>': 86, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '253896', 'n_tokens_mistral': 15503, 'n_tokens_neox': 12692, 'n_words': 3047}