package de.fuberlin.projectci.test.grammar; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import java.io.StringReader; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.junit.Before; import org.junit.Test; import de.fuberlin.projectci.grammar.BNFGrammarReader; import de.fuberlin.projectci.grammar.BNFParsingErrorException; import de.fuberlin.projectci.grammar.Grammar; import de.fuberlin.projectci.grammar.GrammarReader; import de.fuberlin.projectci.grammar.NonTerminalSymbol; import de.fuberlin.projectci.grammar.TerminalSymbol; /** * Testfälle für die Berechnung der FIRST- und FOLLOW-Mengen. * */ public class GrammarTest { private Grammar grammar=null; private Map<NonTerminalSymbol, Set<TerminalSymbol>>nonTerminal2FirstSet=null; private Map<NonTerminalSymbol, Set<TerminalSymbol>>nonTerminal2FollowSet=null; @Before public void setUp() throws Exception { // Testdaten aus: http://www.susigottwald.de/Unistaff/CB_Diplompruefung/Zusammenfassung_Uebersetzerbau.pdf (S.31) String strGrammar="" + "<E> ::= <T> <E1>\n"+ "<E1> ::= \"+\" <T> <E1> | \"@\"\n"+ "<T> ::= <F> <T1>\n"+ "<T1> ::= \"*\" <F> <T1> | \"@\"\n"+ "<F> ::= \"(\" <E> \")\" | \"id\""; GrammarReader grammarReader=new BNFGrammarReader(); try { grammar=grammarReader.readGrammar(new StringReader(strGrammar)); } catch (BNFParsingErrorException e) { fail(e.getClass()+": "+e.getMessage()); } TerminalSymbol ts_id=new TerminalSymbol("id"); TerminalSymbol ts_add=new TerminalSymbol("+"); TerminalSymbol ts_mul=new TerminalSymbol("*"); TerminalSymbol ts_leftp=new TerminalSymbol("("); TerminalSymbol ts_rightp=new TerminalSymbol(")"); TerminalSymbol ts_eof=Grammar.INPUT_ENDMARKER; TerminalSymbol ts_eps=Grammar.EPSILON; NonTerminalSymbol nts_e=new NonTerminalSymbol("E"); NonTerminalSymbol nts_e1=new NonTerminalSymbol("E1"); NonTerminalSymbol nts_t=new NonTerminalSymbol("T"); NonTerminalSymbol nts_t1=new NonTerminalSymbol("T1"); NonTerminalSymbol nts_f=new NonTerminalSymbol("F"); nonTerminal2FirstSet=new HashMap<NonTerminalSymbol, Set<TerminalSymbol>>(); nonTerminal2FollowSet=new HashMap<NonTerminalSymbol, Set<TerminalSymbol>>(); nonTerminal2FirstSet.put(nts_e, new HashSet<TerminalSymbol>(Arrays.asList(new TerminalSymbol[]{ts_leftp, ts_id}))); nonTerminal2FirstSet.put(nts_t, new HashSet<TerminalSymbol>(Arrays.asList(new TerminalSymbol[]{ts_leftp, ts_id}))); nonTerminal2FirstSet.put(nts_f, new HashSet<TerminalSymbol>(Arrays.asList(new TerminalSymbol[]{ts_leftp, ts_id}))); nonTerminal2FirstSet.put(nts_e1, new HashSet<TerminalSymbol>(Arrays.asList(new TerminalSymbol[]{ts_add, ts_eps}))); nonTerminal2FirstSet.put(nts_t1, new HashSet<TerminalSymbol>(Arrays.asList(new TerminalSymbol[]{ts_mul, ts_eps}))); nonTerminal2FollowSet.put(nts_e, new HashSet<TerminalSymbol>(Arrays.asList(new TerminalSymbol[]{ts_rightp, ts_eof}))); nonTerminal2FollowSet.put(nts_e1, new HashSet<TerminalSymbol>(Arrays.asList(new TerminalSymbol[]{ts_rightp, ts_eof}))); nonTerminal2FollowSet.put(nts_t, new HashSet<TerminalSymbol>(Arrays.asList(new TerminalSymbol[]{ts_add, ts_rightp, ts_eof}))); nonTerminal2FollowSet.put(nts_t1, new HashSet<TerminalSymbol>(Arrays.asList(new TerminalSymbol[]{ts_add, ts_rightp, ts_eof}))); nonTerminal2FollowSet.put(nts_f, new HashSet<TerminalSymbol>(Arrays.asList(new TerminalSymbol[]{ts_add, ts_mul, ts_rightp, ts_eof}))); } @Test public void testFirst() { Set<NonTerminalSymbol> nonTerminals = nonTerminal2FirstSet.keySet(); for (NonTerminalSymbol aNonTerminalSymbol : nonTerminals) { Set<TerminalSymbol> result = grammar.first(aNonTerminalSymbol); Set<TerminalSymbol> expected = nonTerminal2FirstSet.get(aNonTerminalSymbol); assertEquals("Symbol: "+aNonTerminalSymbol, expected, result); } } @Test public void testFollow() { Set<NonTerminalSymbol> nonTerminals = nonTerminal2FollowSet.keySet(); for (NonTerminalSymbol aNonTerminalSymbol : nonTerminals) { Set<TerminalSymbol> result = grammar.follow(aNonTerminalSymbol); Set<TerminalSymbol> expected = nonTerminal2FollowSet.get(aNonTerminalSymbol); assertEquals("Symbol: "+aNonTerminalSymbol, expected, result); } } }