ContextFreeGrammar extends Grammar { @SuppressWarnings({"ConstantConditions"}) boolean readBNFString(String bnfString) throws MalformedGrammarException { if(bnfString == null) { return false; } Rule newRule = new Rule(); boolean insertRule = false; Rule currentRule = null; Production newProduction = new Production(); Symbol newSymbol = new Symbol(); String symbolString; Symbol newTokenSeparator = new Symbol(); int bnfString_size = bnfString.length(); char currentChar; char separated = 0; boolean skip = false; boolean quoted = false; boolean non_terminal = false; StringBuffer currentBuffer = new StringBuffer(bnfString_size); final int START = 0; final int START_RULE = 1; final int LHS_READ = 2; final int PRODUCTION = 3; final int START_OF_LINE = 4; int state=START; int i ; try { for(int pass=0; pass<2; pass++){ i = 0; while(i < bnfString_size) { if(i < bnfString_size) { currentChar = bnfString.charAt(i); } else { currentChar='\n'; } if(bnfString.charAt(i) == '\\') { i++; if(i>=bnfString_size){ throw new MalformedGrammarException("Escape sequence as last char is invalid"); } else { if((non_terminal) && (bnfString.charAt(i) != '\n')){ throw new MalformedGrammarException("Only escaped newline allowed inside non-terminal"); } } if(bnfString.charAt(i)=='\''){ currentChar='\''; } else if(bnfString.charAt(i)=='\''){ currentChar='\''; } else if(bnfString.charAt(i)=='\\'){ currentChar='\\'; } else if(bnfString.charAt(i)=='0'){ currentChar='\0'; } else if(bnfString.charAt(i)=='a'){ currentChar='\007'; } else if(bnfString.charAt(i)=='b'){ currentChar='\b'; } else if(bnfString.charAt(i)=='f'){ currentChar='\f'; } else if(bnfString.charAt(i)=='n'){ currentChar='\n'; } else if(bnfString.charAt(i)=='r'){ currentChar='\r'; } else if(bnfString.charAt(i)=='t'){ currentChar='\t'; } else if(bnfString.charAt(i)=='v'){ currentChar='\013'; } else if(bnfString.charAt(i)=='\n'){ skip=true; } else if(bnfString.charAt(i)=='\r'){ skip=true; if(bnfString.charAt(++i) != '\n'){ throw new MalformedGrammarException("No newlinwe"); } } else{ currentChar=bnfString.charAt(i); } if((!skip) && (pass > 0)){ if(currentBuffer.length() == 0){ newSymbol = new Symbol(); newSymbol.setType(Enums.SymbolType.TSymbol); } currentBuffer.append(currentChar); } } else { switch(state){ case(START): if(currentChar=='\r'){ break; } if(currentChar=='#'){ while(i < bnfString_size && bnfString.charAt(i) != '\n') { i++; } break; } switch(currentChar){ case ' ': case '\t': case '\n': break; case '<': newSymbol = new Symbol(); newSymbol.setType(Enums.SymbolType.NTSymbol); currentBuffer.append(currentChar); state = START_RULE; break; default: throw new MalformedGrammarException("Illegal character `" + currentChar + "' found at start of grammar"); } break; case(START_RULE): if(currentChar=='\r'){ break; } switch(currentChar){ case '\n': throw new MalformedGrammarException("Misplaced newline"); case '>': currentBuffer.append(currentChar); symbolString = currentBuffer.toString(); if(pass==0){ if(findRule(newSymbol) == null){ insertRule=true; newRule.setLHS(new Symbol(symbolString, Enums.SymbolType.NTSymbol)); } else { insertRule=true; } } else { currentRule = findRule(symbolString); if(currentRule == null){ throw new MalformedGrammarException("Current rule is null: " + symbolString); } } currentBuffer.delete(0,currentBuffer.length()); state=LHS_READ; break; default: if(((currentChar=='"')||(currentChar=='|')||(currentChar=='<'))){ throw new MalformedGrammarException("Non escaped special character"); } currentBuffer.append(currentChar); } break; case(LHS_READ): if(currentChar=='\r'){ break; } switch(currentChar){ case ' ': case '\t': case '\n': break; case ':': currentBuffer.append(currentChar); break; case '=': currentBuffer.append(currentChar); String s = currentBuffer.toString(); if( s.compareTo("::=")!=0){ throw new MalformedGrammarException("Something other than ::= was read"); } currentBuffer.delete(0,currentBuffer.length()); newProduction.clear(); state = PRODUCTION; break; default: throw new MalformedGrammarException("Illegal character `" + currentChar + "' found in ::= token"); } break; case(PRODUCTION): if(currentChar=='\r'){ break; } if(pass == 0){ if (currentChar=='\n') { state=START_OF_LINE; } break; } else { switch(currentChar){ case '|': if(quoted){ currentBuffer.append(currentChar); break; } case '\n': separated=0; if((currentBuffer.length() != 0)||(newProduction.size() == 0)){ if(currentBuffer.length() == 0){ newSymbol.setType(Enums.SymbolType.TSymbol); } if(non_terminal){ throw new MalformedGrammarException("Current non-terminal symbol isn't finished"); } symbolString = currentBuffer.toString(); newSymbol.setSymbolString(symbolString); if(newSymbol.getType() == Enums.SymbolType.NTSymbol){ Rule tempRule = findRule(newSymbol); if(tempRule != null){ newProduction.add(new Symbol(newSymbol)); } else{ newProduction.add(new Symbol(newSymbol)); } } else { newProduction.add(new Symbol(newSymbol)); } newSymbol.clear(); } currentRule.add(new Production(newProduction)); currentBuffer.delete(0,currentBuffer.length()); if(currentChar=='\n') state=START_OF_LINE; else{ newProduction.clear(); } break; case '<': case '>': case ' ': case '\t': if((quoted) || (((currentChar==' ') || (currentChar=='\t')) && (non_terminal))){ currentBuffer.append(currentChar); if(!non_terminal) { newSymbol.setType(Enums.SymbolType.TSymbol); } break; } if(currentChar=='>'){ currentBuffer.append(currentChar); non_terminal = false; } if(currentBuffer.length() != 0){ if(non_terminal){ throw new MalformedGrammarException("Current non-terminal symbol isn't finished"); } if((currentChar==' ')||(currentChar=='\t')){ separated = 1; } symbolString = currentBuffer.toString(); newSymbol.setSymbolString(symbolString); if(newSymbol.getType()==Enums.SymbolType.NTSymbol){ Rule tempRule = findRule(newSymbol); if(tempRule != null){ newProduction.add(new Symbol(newSymbol)); } else{ newProduction.add(new Symbol(newSymbol)); } } else{ newProduction.add(new Symbol(newSymbol)); } newSymbol.clear(); } else{ if(((currentChar==' ') || (currentChar=='\t')) && (newProduction.size() != 0)){ separated=1; } } currentBuffer.delete(0,currentBuffer.length()); if(currentChar == '<'){ newSymbol.clear(); newSymbol.setType(Enums.SymbolType.NTSymbol); currentBuffer.append(currentChar); non_terminal = true; if(separated == '1'){ separated=0; newTokenSeparator.clear(); newTokenSeparator.setSymbolString(" "); newTokenSeparator.setType(Enums.SymbolType.TSymbol); newProduction.add(new Symbol(newTokenSeparator)); } } break; default: if(separated == '1'){ separated=0; newTokenSeparator.clear(); newTokenSeparator.setSymbolString(" "); newTokenSeparator.setType(Enums.SymbolType.TSymbol); newProduction.add(new Symbol(newTokenSeparator)); } if(currentChar=='"'){ quoted = !quoted; newSymbol.setType(Enums.SymbolType.TSymbol); break; } if(currentBuffer.length() == 0){ newSymbol.setType(Enums.SymbolType.TSymbol); } currentBuffer.append(currentChar); } break; } case(START_OF_LINE): if(currentChar=='#'){ while(i < bnfString_size && bnfString.charAt(i) != '\n') { i++; } break; } if(currentChar=='\r'){ break; } switch(currentChar){ case ' ': case '\t': case '\n': break; case '|': state=PRODUCTION; if(pass==1){ newProduction.clear(); } break; case '<': if(pass==0){ if(insertRule){ rules.add(new Rule(newRule)); } } newSymbol.setType(Enums.SymbolType.NTSymbol); currentBuffer.append(currentChar); state=START_RULE; break; default: throw new MalformedGrammarException("Illegal character `" + currentChar + "' found at start of line"); } break; default: throw new MalformedGrammarException("Impossible error, quit the program now!"); } } skip=false; i++; } if(state!=START_OF_LINE){ throw new MalformedGrammarException("START_OF_LINE must be the state of the parser"); } if(pass==0){ if(insertRule){ this.rules.add(new Rule(newRule)); } } } checkInfiniteRecursion(); } catch (MalformedGrammarException ex) { this.setValidGrammar(false); logger.error("Exception parsing grammar", ex); throw ex; } updateRuleFields(); setValidGrammar(true); genotype2Phenotype(); return true; } ContextFreeGrammar();   ContextFreeGrammar(ContextFreeGrammar g); abstract boolean genotype2Phenotype(); abstract boolean phenotype2Genotype(); abstract int getUsedCodons(); abstract int getUsedWraps(); @SuppressWarnings({"UnusedReturnValue", "IOResourceOpenedButNotSafelyClosed"}) boolean readBNFFile(String file_name); Rule findRule(Symbol s); Rule findRule(String s); ArrayList getTerminalRules(); ArrayList getNonTerminalRules();  }
@Test public void testReadBNFString() throws MalformedGrammarException { System.out.println("* ContextFreeGrammarTest: readBNFString"); String bnfString = ""; ContextFreeGrammarMock instance = new ContextFreeGrammarMock(); boolean result = false; try { result = instance.readBNFString(bnfString); fail("Expected a Malformed Grammar Exception"); } catch (MalformedGrammarException ex) { } assertEquals(false, result); bnfString = instance.readBNFFileToString(this.file_name); instance = new ContextFreeGrammarMock(); assertEquals(true, instance.readBNFString(bnfString)); instance = new ContextFreeGrammarMock(); result = true; try { result = instance.readBNFString(null); } catch (MalformedGrammarException ex) { } catch (NullPointerException e) { assertTrue(true); } assertEquals(false, result); }