package compiler;
import static compiler.Macro.Strategy.AS;
import static compiler.Macro.Strategy.REPLACES;
import static compiler.Macro.Strategy.UNDER;
import static compiler.Macro.Strategy.CALLED;
import static compiler.util.MatchCreator.new_match;
import static compiler.util.StringMatcher.matchString;
import static grammar.GrammarDSL.ref;
import static grammar.GrammarDSL.seq;
import static grammar.GrammarDSL.str;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static trees.MatchSpec.rule;
import static util.MemberAccessor.invoke;
import compiler.macros.MacroInterface;
import compiler.util.Quoter;
import driver.Context;
import grammar.Expression;
import grammar.Grammar;
import grammar.java._E_MacroDefinitions;
import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.junit.runners.MethodSorters;
import parser.Match;
@RunWith(JUnit4.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class MacroExpanderTests
{
/****************************************************************************/
static Grammar old;
static final Grammar grammar = new Grammar(_E_MacroDefinitions.class);
static final MacroExpander expander = new MacroExpander();
/****************************************************************************/
@BeforeClass public static void setUp()
{
old = Context.get().grammar();
invoke(Context.get(), "setGrammar", grammar);
}
/****************************************************************************/
@BeforeClass public static void tearDown()
{
if (old != null) invoke(Context.get(), "setGrammar", old);
}
//============================================================================
class Macro1 implements MacroInterface {
@Override public Match expand(Match input) { return quote("42"); }
}
class Macro2 implements MacroInterface {
@Override public Match expand(Match input) { return quote("/macro1/"); }
}
class Macro3 implements MacroInterface {
@Override public Match expand(Match input) {
return new_match("macro3_dummy", quote("42"));
}
}
class Macro4 implements MacroInterface {
@Override public Match expand(Match input) {
return new_match("macro4_dummy", quote("/macro3/"));
}
}
class Macro5 implements MacroInterface {
@Override public Match expand(Match input) {
return new_match("macro5_dummy", quote("42"));
}
}
class Macro6 implements MacroInterface {
@Override public Match expand(Match input) {
return new_match("macro6_dummy", quote("/macro5/"));
}
}
class Macro7 implements MacroInterface {
@Override public Match expand(Match input) { return quote("/macro2/"); }
}
static class Macro8 implements MacroInterface {
@Override public Match expand(Match input) {
return input.first(rule("expression"));
}
}
Expression m8s = seq(
str("/macro8/"), ref("lCuBra"), ref("expression"), ref("rCuBra"));
static class Macro9 implements MacroInterface {
@Override public Match expand(Match input) {
return Quoter.dynamicQuote("expression", "\"#1\"",
input.first(rule("expression")).string());
}
}
Expression m9s = seq(
str("/macro9/"), ref("lCuBra"), ref("expression"), ref("rCuBra"));
Expression m11s = seq(str("/macro11/"), ref("macro10"));
static class Macro12 implements MacroInterface {
@Override public Match expand(Match input) {
return Quoter.dynamicQuote("expression", "\"#1\"",
input.first(rule("macro10")).string());
}
}
Expression m12s = seq(str("/macro12/"), ref("macro10"));
/****************************************************************************/
Match quote(String code)
{
return Quoter.dynamicQuote("expression", code);
}
/****************************************************************************/
Macro macro(int n, Expression syntax, MacroInterface iface,
Macro.Strategy strat, boolean raw)
{
return new Macro("macro" + n, strat == CALLED ? null : "expression",
grammar, syntax, iface, strat, raw, false);
}
/****************************************************************************/
Macro smacro(int n, MacroInterface iface, Macro.Strategy type, boolean raw)
{
return macro(n, str("/macro" + n + "/"), iface, type, raw);
}
/****************************************************************************/
Match testParse(int n)
{
return testParse(n, "/macro" + n + "/");
}
/****************************************************************************/
Match testParse(int n, String mstr)
{
Match m = matchString(mstr, "expression");
assertEquals(mstr, m.string());
assertTrue(m.is (rule("expression")));
assertTrue(m.child().is(rule("macro" + n)));
return m;
}
/****************************************************************************/
@Test public void aa_test()
{
Macro macro1 = smacro(1, new Macro1(), AS, false);
Macro macro2 = smacro(2, new Macro2(), AS, false);
Macro macro3 = smacro(3, new Macro3(), UNDER, false);
Macro macro4 = smacro(4, new Macro4(), UNDER, false);
Macro macro5 = smacro(5, new Macro5(), REPLACES, false);
Macro macro6 = smacro(6, new Macro6(), REPLACES, false);
Macro macro7 = smacro(7, new Macro7(), AS, false);
Macro macro8 = macro(8, m8s, new Macro8(), AS, false);
Macro macro8r = macro(8, m8s, new Macro8(), AS, true);
Macro macro9 = macro(9, m9s, new Macro9(), AS, true);
Macro macro10 = smacro(10, new Macro1(), CALLED, false);
macro10.enable();
Macro macro11 = macro(11, m11s, new Macro1(), AS, false);
Macro macro12 = macro(12, m12s, new Macro12(), AS, false);
Match m1, m2;
macro1.enable();
m1 = testParse(1);
m2 = expander.transform(m1);
assertEquals("42" , m2.string());
assertTrue (m2.is (rule("expression")));
assertFalse(m2.has(rule("macro1")));
macro2.enable();
m1 = testParse(2);
m2 = expander.transform(m1);
assertEquals("42", m2.string());
assertTrue (m2.is (rule("expression")));
assertFalse(m2.has(rule("macro1")));
assertFalse(m2.has(rule("macro2")));
macro3.enable();
m1 = testParse(3);
m2 = expander.transform(m1);
assertEquals("42", m2.string());
assertTrue(m2.is (rule("expression")));
assertTrue(m2.child().is(rule("macro3_dummy")));
macro4.enable();
m1 = testParse(4);
m2 = expander.transform(m1);
assertEquals("42", m2.string());
assertTrue (m2.is (rule("expression")));
assertTrue (m2.child().is(rule("macro4_dummy")));
assertTrue (m2.child().child().is(rule("expression")));
assertTrue (m2.child().child().child().is(rule("macro3_dummy")));
assertFalse(m2.has(rule("macro3")));
assertFalse(m2.has(rule("macro4")));
macro5.enable();
m1 = testParse(5);
m2 = expander.transform(m1);
assertEquals("42", m2.string());
assertTrue (m2.is(rule("macro5_dummy")));
assertFalse(m2.has(rule("macro5")));
macro6.enable();
m1 = testParse(6);
m2 = expander.transform(m1);
assertEquals("42", m2.string());
assertTrue (m2.is (rule("macro6_dummy")));
assertTrue (m2.child().is(rule("macro5_dummy")));
assertFalse(m2.has(rule("macro5")));
assertFalse(m2.has(rule("macro6")));
macro7.enable();
m1 = testParse(7);
m2 = expander.transform(m1);
assertEquals("42", m2.string());
assertTrue (m2.is (rule("expression")));
assertFalse(m2.has(rule("macro7")));
assertFalse(m2.has(rule("macro1")));
macro8.enable();
m1 = testParse(8, "/macro8/{/macro1/}");
m2 = expander.transform(m1);
assertEquals("42", m2.string());
assertTrue (m2.is(rule("expression")));
assertFalse(m2.has(rule("macro8")));
assertFalse(m2.has(rule("macro1")));
m1 = testParse(8, "/macro8/{/macro8/{/macro1/}}");
m2 = expander.transform(m1);
assertEquals("42", m2.string());
assertTrue (m2.is(rule("expression")));
assertFalse(m2.has(rule("macro8")));
assertFalse(m2.has(rule("macro1")));
macro8.disable();
macro8r.enable();
m1 = testParse(8, "/macro8/{/macro1/}");
m2 = expander.transform(m1);
assertEquals("42", m2.string());
assertTrue (m2.is(rule("expression")));
assertFalse(m2.has(rule("macro8")));
assertFalse(m2.has(rule("macro1")));
m1 = testParse(8, "/macro8/{/macro8/{/macro1/}}");
m2 = expander.transform(m1);
assertEquals("42", m2.string());
assertTrue (m2.is(rule("expression")));
assertFalse(m2.has(rule("macro8")));
assertFalse(m2.has(rule("macro1")));
macro9.enable();
m1 = testParse(9, "/macro9/{/macro1/}");
m2 = expander.transform(m1);
assertEquals("\"/macro1/\"", m2.string());
assertTrue(m2.child().has(rule("stringLiteral")));
macro11.enable();
m1 = testParse(11, "/macro11//macro10/");
m2 = expander.transform(m1);
assertEquals("42", m2.string());
macro12.enable();
m1 = testParse(12, "/macro12//macro10/");
m2 = expander.transform(m1);
assertEquals("\"/macro10/\"", m2.string());
}
}