Search in sources :

Example 1 with CtxVarInst

use of com.squarespace.template.Instructions.CtxVarInst in project template-compiler by Squarespace.

the class InstructionReprTest method testCtxVarRepr.

@Test
public void testCtxVarRepr() {
    CtxVarInst c1 = maker().ctxvar("@foo", "foo=bar.baz");
    assertEquals(c1.repr(), "{.ctx @foo foo=bar.baz}");
    CtxVarInst c2 = maker().ctxvar("@bar", "a=foo.bar.baz.quux", "b=bar.baz.foo", "c=foo.quux.bar.baz");
    assertEquals(c2.repr(), "{.ctx @bar a=foo.bar.baz.quux b=bar.baz.foo c=foo.quux.bar.baz}");
}
Also used : CtxVarInst(com.squarespace.template.Instructions.CtxVarInst) Test(org.testng.annotations.Test)

Example 2 with CtxVarInst

use of com.squarespace.template.Instructions.CtxVarInst in project template-compiler by Squarespace.

the class TokenizerCoreTest method testCtxVar.

@Test
public void testCtxVar() throws CodeSyntaxException {
    CodeMaker mk = maker();
    assertResult("{.ctx @foo a=foo.bar b=baz}", mk.ctxvar("@foo", "a=foo.bar", "b=baz"), mk.eof());
    assertFailure("{.ctx}", WHITESPACE_EXPECTED);
    assertFailure("{.ctx }", CTXVAR_EXPECTS_NAME);
    assertFailure("{.ctx @foo}", WHITESPACE_EXPECTED);
    assertFailure("{.ctx @foo }", CTXVAR_EXPECTS_BINDINGS);
    assertFailure("{.ctx @foo a}", CTXVAR_EXPECTS_BINDINGS);
    assertFailure("{.ctx @foo a=}", CTXVAR_EXPECTS_BINDINGS);
    CtxVarInst c1 = mk.ctxvar("@foo", "a=b");
    assertResult("{.ctx @foo a=b}", c1, mk.eof());
    assertResult("{.ctx @foo a=b }", c1, mk.eof());
    assertResult("{.ctx @foo a=b c}", c1, mk.eof());
    assertResult("{.ctx @foo a=b c=}", c1, mk.eof());
    CtxVarInst c2 = mk.ctxvar("@foo", "a=b", "c=d");
    assertResult("{.ctx @foo a=b c=d}", c2, mk.eof());
    assertResult("{.ctx @foo a=b c=d }", c2, mk.eof());
    assertResult("{.ctx @foo a=b c=d e}", c2, mk.eof());
}
Also used : CtxVarInst(com.squarespace.template.Instructions.CtxVarInst) Test(org.testng.annotations.Test)

Example 3 with CtxVarInst

use of com.squarespace.template.Instructions.CtxVarInst in project template-compiler by Squarespace.

the class Tokenizer method parseInstruction.

/**
 * We've found the start of an instruction. Parse the rest of the range.
 */
private boolean parseInstruction(InstructionType type, int start, int end) throws CodeSyntaxException {
    switch(type) {
        case ALTERNATES_WITH:
            // Look for SPACE "WITH" EOF
            if (!matcher.space()) {
                fail(error(SyntaxErrorType.WHITESPACE_EXPECTED).data(matcher.remainder()));
                return emitInvalid();
            }
            matcher.consume();
            if (!matcher.wordWith()) {
                fail(error(MISSING_WITH_KEYWORD).data(matcher.remainder()));
                return emitInvalid();
            }
            matcher.consume();
            if (!matcher.finished()) {
                fail(error(EXTRA_CHARS).type(type).data(matcher.remainder()));
                return emitInvalid();
            }
            emitInstruction(maker.alternates());
            return true;
        case BINDVAR:
            {
                if (!skipWhitespace()) {
                    return emitInvalid();
                }
                // Parse the variable name.
                if (!matcher.localVariable()) {
                    fail(error(BINDVAR_EXPECTS_NAME).data(matcher.remainder()));
                    return emitInvalid();
                }
                String name = matcher.consume().repr();
                if (!skipWhitespace()) {
                    return emitInvalid();
                }
                Variables vars = parseVariables();
                if (vars == null) {
                    fail(error(MISSING_VARIABLE_NAME).data(matcher.remainder()));
                    return emitInvalid();
                }
                BindVarInst instruction = maker.bindvar(name, vars);
                List<FormatterCall> formatters = parseFormatters(instruction, start);
                if (formatters == null) {
                    emitInstruction(instruction);
                } else if (!formatters.isEmpty()) {
                    instruction.setFormatters(formatters);
                    emitInstruction(instruction);
                }
                return true;
            }
        case CTXVAR:
            {
                if (!skipWhitespace()) {
                    return emitInvalid();
                }
                // Parse the variable name
                if (!matcher.localVariable()) {
                    fail(error(CTXVAR_EXPECTS_NAME).data(matcher.remainder()));
                    return emitInvalid();
                }
                String name = matcher.consume().repr();
                if (!skipWhitespace()) {
                    return emitInvalid();
                }
                List<Binding> bindings = parseBindings();
                if (bindings == null) {
                    fail(error(CTXVAR_EXPECTS_BINDINGS).data(matcher.remainder()));
                    return emitInvalid();
                }
                CtxVarInst instruction = maker.ctxvar(name, bindings);
                emitInstruction(instruction);
                return true;
            }
        case EVAL:
            {
                if (!skipWhitespace()) {
                    return emitInvalid();
                }
                // Instruction has a single argument, a free-form expression
                StringView code = matcher.remainder();
                // The expression will be parsed and assembled the first time
                // the instruction is executed.
                EvalInst instruction = maker.eval(code.toString());
                emitInstruction(instruction);
                return true;
            }
        case END:
        case META_LEFT:
        case META_RIGHT:
        case NEWLINE:
        case SPACE:
        case TAB:
            // Nothing should follow these instructions.
            if (!matcher.finished()) {
                fail(error(EXTRA_CHARS).type(type).data(matcher.remainder()));
                return emitInvalid();
            }
            emitInstruction(maker.simple(type));
            return true;
        case IF:
            return parseIfExpression();
        case INCLUDE:
            {
                // this instruction accepts space-delimited arguments
                if (!matcher.space()) {
                    return emitInvalid();
                }
                // argument delimiter.
                if (!matcher.arguments()) {
                    return emitInvalid();
                }
                StringView rawArgs = matcher.consume();
                Arguments args = new Arguments(rawArgs);
                if (args.count() < 1) {
                    return emitInvalid();
                }
                IncludeInst instruction = maker.include(args);
                emitInstruction(instruction);
                return true;
            }
        case INJECT:
            {
                if (!skipWhitespace()) {
                    return emitInvalid();
                }
                if (!matcher.localVariable()) {
                    fail(error(INJECT_EXPECTS_NAME).data(matcher.remainder()));
                    return emitInvalid();
                }
                String variable = matcher.consume().repr();
                if (!skipWhitespace()) {
                    return emitInvalid();
                }
                if (!matcher.path()) {
                    fail(error(INJECT_EXPECTS_PATH).data(matcher.remainder()));
                    return emitInvalid();
                }
                String path = matcher.consume().repr();
                StringView rawArgs = null;
                Arguments args = Constants.EMPTY_ARGUMENTS;
                if (matcher.arguments()) {
                    rawArgs = matcher.consume();
                    args = new Arguments(rawArgs);
                }
                InjectInst instruction = maker.inject(variable, path, args);
                emitInstruction(instruction);
                return true;
            }
        case MACRO:
            {
                if (!skipWhitespace()) {
                    return emitInvalid();
                }
                if (!matcher.path()) {
                    fail(error(MACRO_EXPECTS_NAME));
                    return emitInvalid();
                }
                StringView path = matcher.consume();
                if (!matcher.finished()) {
                    fail(error(EXTRA_CHARS).type(type).data(matcher.remainder()));
                    return emitInvalid();
                }
                MacroInst inst = maker.macro(path.repr());
                emitInstruction(inst);
                return true;
            }
        case OR_PREDICATE:
            if (matcher.space()) {
                matcher.consume();
                if (!matcher.predicate()) {
                    fail(error(OR_EXPECTED_PREDICATE).type(type).data(matcher.remainder()));
                    return emitInvalid();
                }
                Predicate predicate = resolvePredicate(matcher.consume());
                Arguments args = parsePredicateArguments(predicate);
                if (args == null) {
                    // Error was emitted by parsePredicateArguments()
                    return emitInvalid();
                }
                PredicateInst inst = maker.predicate(predicate, args);
                inst.setOr();
                emitInstruction(inst);
                return true;
            }
            if (!matcher.finished()) {
                fail(error(EXTRA_CHARS).type(type).data(matcher.remainder()));
                return emitInvalid();
            }
            emitInstruction(maker.or());
            return true;
        case REPEATED:
        case SECTION:
            return parseSection(type);
        default:
            throw new RuntimeException("Resolution failure: instruction type '" + type + "' has no text representation.");
    }
}
Also used : PredicateInst(com.squarespace.template.Instructions.PredicateInst) IncludeInst(com.squarespace.template.Instructions.IncludeInst) MacroInst(com.squarespace.template.Instructions.MacroInst) CtxVarInst(com.squarespace.template.Instructions.CtxVarInst) EvalInst(com.squarespace.template.Instructions.EvalInst) BindVarInst(com.squarespace.template.Instructions.BindVarInst) InjectInst(com.squarespace.template.Instructions.InjectInst) ArrayList(java.util.ArrayList) List(java.util.List)

Example 4 with CtxVarInst

use of com.squarespace.template.Instructions.CtxVarInst in project template-compiler by Squarespace.

the class InstructionEqualityTest method testCtxVarEquals.

@Test
public void testCtxVarEquals() throws CodeSyntaxException {
    CodeMaker mk = maker();
    CtxVarInst c1 = mk.ctxvar("foo", "foo=bar.baz", "quux=foo.1.bar.2");
    CtxVarInst c2 = mk.ctxvar("foo", "foo=bar.baz", "quux=foo.1.bar.2");
    assertEquals(c1, c2);
    CtxVarInst c3 = mk.ctxvar("bar", "foo=bar.baz", "quux=foo.1.bar.2");
    assertNotEquals(c1, c3);
    CtxVarInst c4 = mk.ctxvar("foo", "foo.bar.quux", "quux=foo.1.bar.2");
    assertNotEquals(c1, c4);
}
Also used : CtxVarInst(com.squarespace.template.Instructions.CtxVarInst) Test(org.testng.annotations.Test)

Aggregations

CtxVarInst (com.squarespace.template.Instructions.CtxVarInst)4 Test (org.testng.annotations.Test)3 BindVarInst (com.squarespace.template.Instructions.BindVarInst)1 EvalInst (com.squarespace.template.Instructions.EvalInst)1 IncludeInst (com.squarespace.template.Instructions.IncludeInst)1 InjectInst (com.squarespace.template.Instructions.InjectInst)1 MacroInst (com.squarespace.template.Instructions.MacroInst)1 PredicateInst (com.squarespace.template.Instructions.PredicateInst)1 ArrayList (java.util.ArrayList)1 List (java.util.List)1