This is the code I am working with. It parses a text file and prints the results to the screen. The text it parses has a specific format it follows so most of the methods are repetitive. The input text is as follows:
I need to make this into a recursive decent parser. I completely misunderstood what I was supposed to do. Input file the program reads
public class FileParser {
private static Scanner scan;
private static String getLabel(String labelFile) {
int i;
labelFile.trim();
for (i = 0; i < labelFile.length(); i ) {
char charVal = labelFile.charAt(i);
boolean bool = Character.isLetter(charVal);
if (!bool) {
break;
}
}
return labelFile.substring(0, i);
}
public static void main(String[] args) {
try {
File inputFile = new File("C:/Users/corey/OneDrive/Desktop/Input.txt");
String mainStr, mainLabel;
scan = new Scanner(inputFile);
if (scan.hasNextLine()) {
mainStr = scan.nextLine().trim();
mainLabel = getLabel(mainStr);
if (!mainLabel.equalsIgnoreCase("Window")) {// gui ::= Window
System.out.println("Incorrect Input file should start with WINDOW");
return;
}
mainStr = mainStr.substring(mainLabel.length()).trim();
JFrame mainFrame = (JFrame) addCompnt(mainStr, mainLabel);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setVisible(true);
} else {
System.out.println("Error");
}
} catch (FileNotFoundException fnfe) {
System.out.println("File not found");
fnfe.toString();
} catch (Exception unk) {
System.out.println("Unknown Error");
unk.toString();
}
}
private static ArrayList<Integer> getArray(String arrayStr) throws Exception {
int x, y;
ArrayList<Integer> arrayInt = new ArrayList<Integer>();
for (x = 0; x < arrayStr.length(); x ) {
for (y = x; y < arrayStr.length() && Character.isDigit(arrayStr.charAt(y)); y );
if (x != y) {
arrayInt.add(Integer.parseInt(arrayStr.substring(x, y)));
}
x = y;
}
return arrayInt;
}
private static Component addCompnt(String compntStr, String compntLabel) throws Exception {
String inputStr;
if (compntLabel.equalsIgnoreCase("Window")) {// gui ::= Window STRING
compntStr = compntStr.trim();
JFrame wndwFrame;
if (compntStr.charAt(0) == '"') {
compntStr = compntStr.substring(1);
inputStr = compntStr.substring(0, compntStr.indexOf('"'));
wndwFrame = new JFrame(inputStr);
compntStr = compntStr.substring(compntStr.indexOf('"') 1).trim();
} else {
wndwFrame = new JFrame("Missing Window Title");
}
if (compntStr.charAt(0) == '(') {// gui ::= '(' NUMBER ',' NUMBER ')' layout widgets End '.'
inputStr = compntStr.substring(0, compntStr.indexOf(')') 1);
compntStr = compntStr.substring(inputStr.length()).trim();
ArrayList<Integer> intStr = getArray(inputStr);
if (intStr.size() == 2) {
wndwFrame.setSize(intStr.get(0), intStr.get(1));
}
}
inputStr = getLabel(compntStr);
compntStr = compntStr.substring(inputStr.length()).trim();
JPanel loPanel = new JPanel();
if (inputStr.equalsIgnoreCase("Layout")) {// layout ::= Layout layout_type ':'
inputStr = getLabel(compntStr);
compntStr = compntStr.substring(inputStr.length()).trim();
if (inputStr.equalsIgnoreCase("Flow")) {// layout_type ::= Flow
FlowLayout fLayout = new FlowLayout();
loPanel.setLayout(fLayout);
}
if (inputStr.equalsIgnoreCase("Grid")) {// layout_type ::= Grid
if (compntStr.charAt(0) == '(') {
inputStr = compntStr.substring(0, compntStr.indexOf(')') 1);
compntStr = compntStr.substring(inputStr.length()).trim();
ArrayList<Integer> intStr = getArray(inputStr); // layout_type ::= NUMBER ',' NUMBER ',' NUMBER
GridLayout gLayout;
if (intStr.size() == 2) {
gLayout = new GridLayout(intStr.get(0), intStr.get(1));
loPanel.setLayout(gLayout);
} else if (intStr.size() == 4) {
gLayout = new GridLayout(intStr.get(0), intStr.get(1), intStr.get(2), intStr.get(3));
loPanel.setLayout(gLayout);
}
}
}
}
while (true) {
if (scan.hasNextLine()) {
compntStr = scan.nextLine().trim();
inputStr = getLabel(compntStr);
if (inputStr.equalsIgnoreCase("end")) {// gui ::= End '.'
break;
} else {
Component nestCompnt = addCompnt(compntStr.substring(inputStr.length()), inputStr);
if (nestCompnt != null) {
if (nestCompnt.getClass() == wndwFrame.getClass()) {
System.out.println("Window can't be nested inside");
} else {
loPanel.add(nestCompnt);
}
}
}
} else {
break;
}
}
wndwFrame.add(loPanel);
return wndwFrame;
}
if (compntLabel.equalsIgnoreCase("Button")) {// widget ::= Button STRING ';'
compntStr = compntStr.trim();
JButton widgetBttn;
if (compntStr.charAt(0) == '"') {
compntStr = compntStr.substring(1);
inputStr = compntStr.substring(0, compntStr.indexOf('\"'));
widgetBttn = new JButton(inputStr);
compntStr = compntStr.substring(compntStr.indexOf('"') 1).trim();
} else {
widgetBttn = new JButton("Missing Button Label");
}
return widgetBttn;
}
if (compntLabel.equalsIgnoreCase("Group")) {// widget ::= Group radio_button END ';'
compntStr = compntStr.trim();
JRadioButton grpBttn;
if (compntStr.charAt(0) == '"') {
compntStr = compntStr.substring(1);
inputStr = compntStr.substring(0, compntStr.indexOf('\"'));
grpBttn = new JRadioButton(inputStr);
compntStr = compntStr.substring(compntStr.indexOf('"') 1).trim();
} else {
grpBttn = new JRadioButton("Missing Group Label");
}
return grpBttn;
}
if (compntLabel.equalsIgnoreCase("Label")) {// widget ::= Label STRING ';'
compntStr = compntStr.trim();
JLabel widgetLabel;
if (compntStr.charAt(0) == '"') {
compntStr = compntStr.substring(1);
inputStr = compntStr.substring(0, compntStr.indexOf('\"'));
widgetLabel = new JLabel(inputStr);
compntStr = compntStr.substring(compntStr.indexOf('"') 1).trim();
} else {
widgetLabel = new JLabel("Missing Label");
}
return widgetLabel;
}
if (compntLabel.equalsIgnoreCase("Panel")) {// widget ::= Panel layout widgets End ';'
compntStr = compntStr.trim();
JPanel compntPnl = new JPanel();
inputStr = getLabel(compntStr);
compntStr = compntStr.substring(inputStr.length()).trim();
if (inputStr.equalsIgnoreCase("Layout")) {
inputStr = getLabel(compntStr);
compntStr = compntStr.substring(inputStr.length()).trim();
if (inputStr.equalsIgnoreCase("Flow")) {// layout_type ::= Flow
FlowLayout panelFlow = new FlowLayout();
compntPnl.setLayout(panelFlow);
}
if (inputStr.equalsIgnoreCase("Grid")) {// layout_type ::= Grid
if (compntStr.charAt(0) == '(') {
inputStr = compntStr.substring(0, compntStr.indexOf(')') 1);
compntStr = compntStr.substring(inputStr.length()).trim();
ArrayList<Integer> gridStrg = getArray(inputStr);
GridLayout gLayout;
if (gridStrg.size() == 2) {
gLayout = new GridLayout(gridStrg.get(0), gridStrg.get(1));
compntPnl.setLayout(gLayout);
} else if (gridStrg.size() == 4) {
gLayout = new GridLayout(gridStrg.get(0), gridStrg.get(1), gridStrg.get(2),
gridStrg.get(3));
compntPnl.setLayout(gLayout);
}
}
}
}
while (true) {
if (scan.hasNextLine()) {
compntStr = scan.nextLine().trim();
inputStr = getLabel(compntStr);
if (inputStr.equalsIgnoreCase("End")) {
break;
} else {
Component errCompnt = addCompnt(compntStr.substring(inputStr.length()), inputStr);
if (errCompnt != null) {
if (errCompnt.getClass() == new JFrame().getClass()) {
System.out.println("Panel Layout Error");
} else {
compntPnl.add(errCompnt);
}
}
}
} else {
System.out.println("Error in Panel Layout Nesting");
break;
}
}
return compntPnl;
}
if (compntLabel.equalsIgnoreCase("Textfield")) {// widget ::= Textfield NUMBER ';'
compntStr = compntStr.trim();
ArrayList<Integer> textStr = getArray(compntStr);
JTextField txtFld = new JTextField(textStr.get(0));
return txtFld;
}
if (compntLabel.equalsIgnoreCase("Radio")) {// widget ::= Radio STRING ';'
compntStr = compntStr.trim();
JRadioButton rdoBttn;
if (compntStr.charAt(0) == '"') {
compntStr = compntStr.substring(1);
inputStr = compntStr.substring(0, compntStr.indexOf('\"'));
rdoBttn = new JRadioButton(inputStr);
compntStr = compntStr.substring(compntStr.indexOf('"') 1).trim();
} else {
rdoBttn = new JRadioButton("Missing Radio Label");
}
return rdoBttn;
}
return null;
}
}
CodePudding user response:
You can try this:
switch(compntLabel.getText().toUpperCase()) { /* your conditions */}
CodePudding user response:
Do you mean something like this? :
if (compntLabel.equalsIgnoreCase("Button") || compntLabel.equalsIgnoreCase("Group") || compntLabel.equalsIgnoreCase("Label")) {
// .. Common code
}
CodePudding user response:
You can use this:
if(compntLabel.equalsIgnoreCase("Button") || compntLabel.equalsIgnoreCase("Group") || compntLabel.equalsIgnoreCase("Label"))
{
.
.
.
}
CodePudding user response:
Add the folloing code in current class.
static String matches[] = {
"Button",
"Group",
"Label"
};
static boolean checkMatch(String component) {
for( String m : matches)
if(component.equals(m))
return true;
return false;
}
And write the following code to do your work.
if(checkMatch(compntLabel)) {
// your code
}
Instead of writing a weird condition to check if one of them is true, you can put all the logic in a method and that method will return true or false accordingly.
In your case the method tries all possible matches (button, label, group and can be extended easily by dding strings to the array matches) and if one of them matches the parameter it returns true, if no one match it returns false.
Note: static keyword may not be needed, depends if the class you are writing the code is static or not.
CodePudding user response:
You can create a Set
and fill it with values that you want to OR
over, then check whether it contains your containerLabel
.
if (Set.of("Button", "Group", "Label").contains(compntLabel)) { ... }
CodePudding user response:
Since I don't have your full code, I cannot voucher that this code below will run; however, I can use the code below to solve some of your issues, plus give you some ideas that can help you to improve your code.
So, first lets go over the whole code I modified and then I will go over each part to explain why I did what I did:
private static final BUTTON_COMPONENT = "button";
private static final GROUP_COMPONENT = "group";
private static final LABEL_COMPONENT = "label";
private String compntStr = "something bla bla bla";
private JComponent doSomething(){
JComponent component = null;
switch(comnptLabel.toLowerCase()){
case BUTTON_COMPONENT:
component = doSomethingElseWithButton(getButton(compntStr));
break;
case GROUP_COMPONENT:
component = getGroup(compntStr);
break;
case LABEL_COMPONENT:
component = getLabel(compntStr);
break;
default:
break;
}
compntStr = postProcessString(compntStr);
return component;
}
private JButton getButton(String compntStr){
if (doStartWithQuote(compntStr)){
return getElement(compntStr);
}
return new T("Missing Button Label");
}
private boolean doStartWithQuote(String compntStr){
compntStr = compntStr.trim();
return compntStr.charAt(0) == '"';
}
private <T extends JComponent> T getElement(String compntStr){
return new T(preProcessString(compntStr));
}
private String preProcessString(String compntStr){
compntStr = compntStr.substring(1);
return compntStr.substring(0, compntStr.indexOf('\"'));
}
private JRadioButton getButton(String compntStr){
if (doStartWithQuote(compntStr)){
return getElement(compntStr);
}
return new T("Missing Group Label");
}
private JButton getButton(String compntStr){
if (doStartWithQuote(compntStr)){
return getElement(compntStr);
}
return new T("Missing Label");
}
private String postProcessString(String compntStr){
return compntStr.substring(compntStr.indexOf('"') 1).trim();
}
Let's start with the piece you are interested in relation of using if statements and such.
The issue of using this kind of line compntLabel.equalsIgnoreCase("Button")
is the amount of processing its involved. Without going into the details, I think that if you lowercase all the characters in compntLabel
, then you can compare with lower case strings, allowing you to use a switch
instead of an if
statement.
private JComponent doSomething(){
JComponent component = null;
switch(comnptLabel.toLowerCase()){
case "button":
component = doSomethingWithButton(getButton(compntStr));
break;
case "group":
component = getGroup(compntStr);
break;
case "label":
component = getLabel(compntStr);
break;
default:
break;
}
compntStr = postProcessString(compntStr);
return component;
}
Next, lets break the code into small reusable methods:
private JButton getButton(String compntStr){
if (doStartWithQuote(compntStr)){
return getElement(compntStr);
}
return new T("Missing Button Label");
}
private boolean doStartWithQuote(String compntStr){
compntStr = compntStr.trim();
return compntStr.charAt(0) == '"';
}
private <T extends JComponent> T getElement(String compntStr){
inputStr = preProcessString(compntStr);
return new T(inputStr);
}
private String preProcessString(String compntStr){
compntStr = compntStr.substring(1);
return compntStr.substring(0, compntStr.indexOf('\"'));
}
I'm using here a Generic method since getElement
does the same thing but returns different types such as JButton
, JRadioButton
, and JLabel
which parent class is JComponent
.
private <T extends JComponent> T getElement(String compntStr){
T widgetBttn;
inputStr = preProcessString(compntStr);
return new T(inputStr);
}
Also, we are reducing duplicate code and put them into methods that we provide names that make sense, saving us to have to write comments.
private boolean doStartWithQuote(String compntStr){
compntStr = compntStr.trim();
return compntStr.charAt(0) == '"';
}
The issues with comments is that if some other developer changes the code but doesn't update the comments, it can create a whole confusion. However, if I put that small piece of code into a method and provide a descriptive name, it save us confusion and make the code easier to read. Plus, if there is an issue, we will be provided with a runtime error that will indicate where the issue is. Easier for us to locate and fix the issue in this way.
Finally, using this approach let us to add new widget component easier:
private JRadioButton getButton(String compntStr){
if (doStartWithQuote(compntStr)){
return getElement(compntStr);
}
return new T("Missing Group Label");
}
private JButton getButton(String compntStr){
if (doStartWithQuote(compntStr)){
return getElement(compntStr);
}
return new T("Missing Label");
}
Also, notices that for each function I call, I try to have it right below the method it calling it. This makes it easier to read up-to-down.
Many of these changes are based on the book "Clean Code" by Robert C. Martin aka. Uncle Bob.
I hope this helped you out. If not, please let me know and I can remove this answer.