SmolinskiW_Program13.java
/**
* William Smolinski
* CISS 111
* Program 13 - Checks a Java source code file for proper nesting of (), {}, []
*/
import java.io.*;
import java.util.Scanner;
public class SmolinskiW_Program13
{
public static void main(String[] args)
{
//Declaring a Scanner to get user input
Scanner keyboard = new Scanner(System.in);
//Declaring the stack to keep track of curly brackets (Separate because they aren't line based)
LinkedStack mainStack = new LinkedStack();
//Declaring the stack to keep track of proper parenthesis and brackets in a line (Ending with ;)
LinkedStack lineStack = new LinkedStack();
boolean canContinue = false;
Scanner inputFile = null;
//Asks the user for a file to check
while(!canContinue)
{
//Try-catch to make sure the file is valid
try
{
System.out.print("Enter the file name to test: ");
File file = new File(keyboard.next());
inputFile = new Scanner(file);
canContinue = true;
}
catch (Exception e)
{
System.out.println("Not a valid file!");
}
}
String line = "";
int lineNum = 0;
boolean fileIsCorrect = true;
boolean checkForCurlyBracket = false;
//Keeps track of what type of break the program is in (comment or literal)
int typeOfBreak = 0;
//Loops for each line in the file or until an error is detected
while(inputFile.hasNext() && fileIsCorrect)
{
//If the last line was a line comment it resets the typeOfBreak because it no longer exists on a new line
if(typeOfBreak == 1)
{
typeOfBreak = 0;
}
line = inputFile.nextLine();
lineNum += 1;
//Loops through each character in the line
for(int i = 0; i < line.length(); i++)
{
if(typeOfBreak == 0)
{
//Not in a comment or literal
char current = line.charAt(i);
if(current == '(' || current == '{' || current == '[')
{
//If the character is an opening symbol it adds it to the stack
if(current == '{')
{
//At the start of a new curly bracket it would mean the parenthesis in the method
//header and those aren't followed by a semicolon so this would mark the end of line
if(!lineStack.empty())
{
fileIsCorrect = false;
}
else
{
//Curly bracket
mainStack.push(current);
}
}
else
{
//Line specific symbols
lineStack.push(current);
}
}
else if(current == ')' || current == '}' || current == ']')
{
//If the character is a closing symbol it checks if the top of the stack is the correct
//opening symbol and removes it, or it ends the program
//CurlyBracket is separate
if(current == '}')
{
if(!mainStack.empty())
{
mainStack.pop();
}
else
{
fileIsCorrect = false;
}
}
else
{
//Checks for proper pairing of opening and closing symbols
if(!lineStack.empty() && ((lineStack.peek() == '(' && current == ')') ||
(lineStack.peek() == '[' && current == ']')))
{
lineStack.pop();
}
else
{
fileIsCorrect = false;
}
}
}
else if(current == ';')
{
//Flags that it is the end of the line
if(!lineStack.empty())
{
//If the symbols on the line don't pair and there are leftovers it marks it as incorrect
fileIsCorrect = false;
}
}
else
{
//Checks if it is the start of a comment or literal
if(i != 0)
{
char last = line.charAt(i - 1);
typeOfBreak = getTypeOfBreak(last, current);
}
}
}
else
{
//In a comment or literal (checks for the end of the comment)
if(i != 0)
{
char current = line.charAt(i);
char last = line.charAt(i - 1);
//Checks to see if the break is ended
if(resolveTypeOfBreak(last, current, typeOfBreak))
{
//Resets typeOfBreak
typeOfBreak = 0;
}
}
}
}
//If a curly bracket is not detected the file fails
if(checkForCurlyBracket && typeOfBreak == 0)
{
//Makes sure the line is not empty
if(line.trim().length() > 0)
{
if(!line.trim().startsWith("{"))
{
fileIsCorrect = false;
}
else
{
checkForCurlyBracket = false;
}
}
}
//If a line ends with a ) without a ; the next line should start with an open curly bracket
if(line.trim().endsWith(")") && typeOfBreak == 0) //Only checks when not in comment
{
checkForCurlyBracket = true;
}
}
//Displays the proper message at the end
if(fileIsCorrect && mainStack.empty())
{
System.out.println("The file has proper nesting of (), {}, []");
}
else
{
System.out.println("Fail detected by line: " + lineNum);
System.out.println("The file does NOT have proper nesting of (), {}, []");
}
//Closes the file
inputFile.close();
}
/**
* Method to determine if the line has entered a commented section or literal
* @param last The last char in the line
* @param current The current char in the line
* @return Returns the type of break as an int to be used to determine when that type of break ends
*/
private static int getTypeOfBreak(char last, char current)
{
if(last == '/' && current == '/')
{
//In a single line comment
return 1;
}
else if(last == '/' && current == '*')
{
//In a multiple line comment
return 2;
}
else if(current == '"' && last != '\\')
{
//In a literal
return 3;
}
else if(current == '\'' && last != '\\')
{
//In a char
return 4;
}
else
{
return 0;
}
}
/**
* Method to determine if the type of break can be resolved or not
* @param last Last char in the line
* @param current current char in the line
* @param type Type of break that was detected
* @return Returns a boolean for whether the break is resolved or not
*/
private static boolean resolveTypeOfBreak(char last, char current, int type)
{
switch(type)
{
case 2:
return (last == '*' && current == '/');
case 3:
return (current == '"' && last != '\\');
case 4:
return (current == '\'' && last != '\\');
}
return false;
}
}