/* Copyright 2009-2016 David Hadka
*
* This file is part of the MOEA Framework.
*
* The MOEA Framework is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* The MOEA Framework is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the MOEA Framework. If not, see <http://www.gnu.org/licenses/>.
*/
package org.moeaframework.util.grammar;
import java.io.IOException;
import java.io.StringReader;
import org.junit.Assert;
import org.junit.Test;
/**
* Tests the {@link Parser} class.
*/
public class ParserTest {
/**
* Tests if the parser correctly handles an empty file, or a file filled
* with whitespace.
*
* @throws IOException should not occur
*/
@Test
public void testEmptyRule() throws IOException {
ContextFreeGrammar g1 = Parser.load(new StringReader(""));
Assert.assertEquals(0, g1.size());
ContextFreeGrammar g2 = Parser.load(new StringReader(
" \r\n \r\n\r\n"));
Assert.assertEquals(0, g2.size());
ContextFreeGrammar g3 = Parser.load(new StringReader(" \n \n\n"));
Assert.assertEquals(0, g3.size());
}
/**
* Tests if the parser correctly ignores C and C++ style comments.
*
* @throws IOException should not occur
*/
@Test
public void testComments() throws IOException {
ContextFreeGrammar g1 = Parser.load(new StringReader(
"//<test> ::= <foo> <bar>"));
Assert.assertEquals(0, g1.size());
ContextFreeGrammar g2 = Parser.load(new StringReader(
"/*<test> ::= <foo> <bar>*/"));
Assert.assertEquals(0, g2.size());
ContextFreeGrammar g3 = Parser.load(new StringReader(
"//<test> ::= <foo> <bar>\n/*<test> ::= <foo> <bar>*/"));
Assert.assertEquals(0, g3.size());
ContextFreeGrammar g4 = Parser.load(new StringReader(
"//<test> ::= <foo> <bar>\n<real> ::= <production>\n/*<test> ::= <foo> <bar>*/"));
Assert.assertEquals(1, g4.size());
Assert.assertEquals(1, g4.get(0).size());
ContextFreeGrammar g5 = Parser.load(new StringReader(
"<inline> ::= <production> //<test> ::= <foo> <bar>"));
Assert.assertEquals(1, g5.size());
Assert.assertEquals(1, g5.get(0).size());
ContextFreeGrammar g6 = Parser.load(new StringReader(
"<inline> ::= /* <commented> */ <production>"));
Assert.assertEquals(1, g6.size());
Assert.assertEquals(1, g6.get(0).size());
}
/**
* Tests if the parser correctly identifies the rule separator in its
* various forms.
*
* @throws IOException should not occur
*/
@Test
public void testRuleSeparator() throws IOException {
ContextFreeGrammar g1 = Parser
.load(new StringReader("<foo> ::= <bar>"));
Assert.assertEquals(1, g1.size());
Assert.assertEquals(1, g1.get(0).size());
ContextFreeGrammar g2 = Parser.load(new StringReader("<foo> : <bar>"));
Assert.assertEquals(1, g2.size());
Assert.assertEquals(1, g2.get(0).size());
ContextFreeGrammar g3 = Parser.load(new StringReader("<foo> = <bar>"));
Assert.assertEquals(1, g3.size());
Assert.assertEquals(1, g3.get(0).size());
ContextFreeGrammar g4 = Parser.load(new StringReader(
"<foo> ::=:==: <bar>"));
Assert.assertEquals(1, g4.size());
Assert.assertEquals(1, g4.get(0).size());
}
/**
* Tests the parser on a simple example.
*
* @throws IOException should not occur
*/
@Test
public void testSimpleExample() throws IOException {
ContextFreeGrammar g = Parser.load(new StringReader(
"<foo> ::= <bar>\n<bar> ::= a | (b) | ( c )"));
Assert.assertEquals(2, g.size());
Assert.assertEquals(1, g.get(0).size());
Assert.assertFalse(g.get(0).getSymbol().isTerminal());
Assert.assertEquals("foo", g.get(0).getSymbol().getValue());
Assert.assertEquals(1, g.get(0).get(0).size());
Assert.assertFalse(g.get(0).get(0).get(0).isTerminal());
Assert.assertEquals("bar", g.get(0).get(0).get(0).getValue());
Assert.assertEquals(3, g.get(1).size());
Assert.assertEquals(3, g.get(1).size());
Assert.assertFalse(g.get(1).getSymbol().isTerminal());
Assert.assertEquals("bar", g.get(1).getSymbol().getValue());
Assert.assertEquals(1, g.get(1).get(0).size());
Assert.assertTrue(g.get(1).get(0).get(0).isTerminal());
Assert.assertEquals("a", g.get(1).get(0).get(0).getValue());
Assert.assertEquals(3, g.get(1).get(1).size());
Assert.assertTrue(g.get(1).get(1).get(0).isTerminal());
Assert.assertEquals("(", g.get(1).get(1).get(0).getValue());
Assert.assertTrue(g.get(1).get(1).get(1).isTerminal());
Assert.assertEquals("b", g.get(1).get(1).get(1).getValue());
Assert.assertTrue(g.get(1).get(1).get(2).isTerminal());
Assert.assertEquals(")", g.get(1).get(1).get(2).getValue());
Assert.assertEquals(3, g.get(1).get(2).size());
Assert.assertTrue(g.get(1).get(2).get(0).isTerminal());
Assert.assertEquals("(", g.get(1).get(2).get(0).getValue());
Assert.assertTrue(g.get(1).get(2).get(1).isTerminal());
Assert.assertEquals("c", g.get(1).get(2).get(1).getValue());
Assert.assertTrue(g.get(1).get(2).get(2).isTerminal());
Assert.assertEquals(")", g.get(1).get(2).get(2).getValue());
}
/**
* Tests if the parser throws an exception if the rule symbol is missing.
*
* @throws GrammarException the expected outcome
*/
@Test(expected = GrammarException.class)
public void testMissingRuleSymbolException() throws IOException {
Parser.load(new StringReader(" ::= <bar>"));
}
/**
* Tests if the parser throws an exception if the rule symbol is not
* surrounded by angle brackets.
*
* @throws GrammarException the expected outcome
*/
@Test(expected = GrammarException.class)
public void testInvalidRuleSymbolException1() throws IOException {
Parser.load(new StringReader("foo ::= <bar>"));
}
/**
* Tests if the parser throws an exception if the rule symbol is not
* surrounded by angle brackets.
*
* @throws GrammarException the expected outcome
*/
@Test(expected = GrammarException.class)
public void testInvalidRuleSymbolException2() throws IOException {
Parser.load(new StringReader("<foo ::= <bar>"));
}
/**
* Tests if the parser throws an exception if the production is empty.
*
* @throws GrammarException the expected outcome
*/
@Test(expected = GrammarException.class)
public void testEmptyProductionException1() throws IOException {
Parser.load(new StringReader("<foo> ::= "));
}
/**
* Tests if the parser throws an exception if the production is incomplete.
*
* @throws GrammarException the expected outcome
*/
@Test(expected = GrammarException.class)
public void testEmptyProductionException2() throws IOException {
Parser.load(new StringReader("<foo> ::= <bar> | "));
}
/**
* Tests if the parser throws an exception if the production is missing a
* rule.
*
* @throws GrammarException the expected outcome
*/
@Test(expected = GrammarException.class)
public void testEmptyProductionException3() throws IOException {
Parser.load(new StringReader("<foo> ::= | <bar>"));
}
/**
* Tests if the parser throws an exception if the rule symbol is the
* empty string.
*
* @throws GrammarException the expected outcome
*/
@Test(expected = GrammarException.class)
public void testEmptySymbolException1() throws IOException {
Parser.load(new StringReader("<> ::= <bar>"));
}
/**
* Tests if the parser throws an exception if a production symbol is the
* empty string.
*
* @throws GrammarException the expected outcome
*/
@Test(expected = GrammarException.class)
public void testEmptySymbolException2() throws IOException {
Parser.load(new StringReader("<foo> ::= <>"));
}
/**
* Tests if the parser correctly handles escaped characters.
*
* @throws IOException should not occur
*/
@Test
public void testEscapedCharacters() throws IOException {
ContextFreeGrammar g = Parser.load(new StringReader(
"<foo> ::= \":\" | '|' | \"<\" | '>'"));
Assert.assertEquals(1, g.size());
Assert.assertEquals(4, g.get(0).size());
Assert.assertEquals(1, g.get(0).get(0).size());
Assert.assertTrue(g.get(0).get(0).get(0).isTerminal());
Assert.assertEquals(":", g.get(0).get(0).get(0).getValue());
Assert.assertEquals(1, g.get(0).get(1).size());
Assert.assertTrue(g.get(0).get(1).get(0).isTerminal());
Assert.assertEquals("|", g.get(0).get(1).get(0).getValue());
Assert.assertEquals(1, g.get(0).get(2).size());
Assert.assertTrue(g.get(0).get(2).get(0).isTerminal());
Assert.assertEquals("<", g.get(0).get(2).get(0).getValue());
Assert.assertEquals(1, g.get(0).get(3).size());
Assert.assertTrue(g.get(0).get(3).get(0).isTerminal());
Assert.assertEquals(">", g.get(0).get(3).get(0).getValue());
}
/**
* Tests if the parser correctly handles single and double quotes.
*
* @throws IOException should not occur
*/
@Test
public void testQuotes() throws IOException {
ContextFreeGrammar g1 = Parser.load(new StringReader(
"<foo> ::= \"bar()\""));
Assert.assertEquals(1, g1.size());
Assert.assertEquals(1, g1.get(0).size());
Assert.assertEquals(1, g1.get(0).get(0).size());
Assert.assertTrue(g1.get(0).get(0).get(0).isTerminal());
Assert.assertEquals("bar()", g1.get(0).get(0).get(0).getValue());
ContextFreeGrammar g2 = Parser.load(new StringReader(
"<foo> ::= 'bar()'"));
Assert.assertEquals(1, g2.size());
Assert.assertEquals(1, g2.get(0).size());
Assert.assertEquals(1, g2.get(0).get(0).size());
Assert.assertTrue(g2.get(0).get(0).get(0).isTerminal());
Assert.assertEquals("bar()", g2.get(0).get(0).get(0).getValue());
}
/**
* Tests if the parser correctly handles integer terminals.
*
* @throws IOException should not occur
*/
@Test
public void testIntegers() throws IOException {
ContextFreeGrammar g = Parser.load(new StringReader(
"<numbers> ::= 8 | -64 256"));
Assert.assertEquals(1, g.size());
Assert.assertEquals(2, g.get(0).size());
Assert.assertEquals(1, g.get(0).get(0).size());
Assert.assertTrue(g.get(0).get(0).get(0).isTerminal());
Assert.assertEquals("8", g.get(0).get(0).get(0).getValue());
Assert.assertEquals(2, g.get(0).get(1).size());
Assert.assertTrue(g.get(0).get(1).get(0).isTerminal());
Assert.assertEquals("-64", g.get(0).get(1).get(0).getValue());
Assert.assertTrue(g.get(0).get(1).get(1).isTerminal());
Assert.assertEquals("256", g.get(0).get(1).get(1).getValue());
}
/**
* Tests if the parser correctly handles decimal terminals.
*
* @throws IOException should not occur
*/
@Test
public void testDecimals() throws IOException {
ContextFreeGrammar g = Parser.load(new StringReader(
"<numbers> ::= 0.0 | -1.2 42.24"));
Assert.assertEquals(1, g.size());
Assert.assertEquals(2, g.get(0).size());
Assert.assertEquals(1, g.get(0).get(0).size());
Assert.assertTrue(g.get(0).get(0).get(0).isTerminal());
Assert.assertEquals("0.0", g.get(0).get(0).get(0).getValue());
Assert.assertEquals(2, g.get(0).get(1).size());
Assert.assertTrue(g.get(0).get(1).get(0).isTerminal());
Assert.assertEquals("-1.2", g.get(0).get(1).get(0).getValue());
Assert.assertTrue(g.get(0).get(1).get(1).isTerminal());
Assert.assertEquals("42.24", g.get(0).get(1).get(1).getValue());
}
}