private Node parseCssClassOrId() { Token tok = nextToken(); Tag div = new Tag("div", line()); lexer.defer(div); lexer.defer(tok); return parseExpr(); }
@SuppressWarnings("rawtypes") private Token accept(Class clazz) { if (this.peek().getClass().equals(clazz)) { return lexer.advance(); } return null; }
private BlockNode parseYield() { nextToken(); BlockNode block = (BlockNode) new BlockNode(); block.setLineNumber(lexer.getLineno()); block.setFileName(filename); block.setYield(true); return block; }
private Node parseExpr() { Token token = peek(); if (token instanceof Tag) { return parseTag(); } if (token instanceof Mixin) { return parseMixin(); } if (token instanceof MixinInject) { return parseMixinInject(); } if (token instanceof Block) { return parseBlock(); } if (token instanceof ExtendsToken) { return parseExtends(); } if (token instanceof Include) { return parseInclude(); } if (token instanceof Filter) { return parseFilter(); } if (token instanceof Comment) { return parseComment(); } if (token instanceof Text) { return parseText(); } if (token instanceof Each) { return parseEach(); } if (token instanceof While) { return parseWhile(); } if (token instanceof CssClass || token instanceof CssId) { return parseCssClassOrId(); } if (token instanceof If) { return parseConditional(); } if (token instanceof CaseToken) { return parseCase(); } if (token instanceof Assignment) { return parseAssignment(); } if (token instanceof Doctype) { return parseDoctype(); } if (token instanceof Expression) { return parseCode(); } if (token instanceof Yield) { return parseYield(); } throw new JadeParserException(filename, lexer.getLineno(), templateLoader, token); }
private Node parseFilter() { Token token = expect(Filter.class); Filter filterToken = (Filter) token; Attribute attr = (Attribute) accept(Attribute.class); lexer.setPipeless(true); Node tNode = parseTextBlock(); lexer.setPipeless(false); FilterNode node = new FilterNode(); node.setValue(filterToken.getValue()); node.setLineNumber(line()); node.setFileName(filename); node.setTextBlock(tNode); if (attr != null) { node.setAttributes(attr.getAttributes()); } return node; }
@SuppressWarnings("rawtypes") private Token expect(Class expectedTokenClass) { Token t = this.peek(); if (t.getClass().equals(expectedTokenClass)) { return nextToken(); } else { throw new JadeParserException( filename, lexer.getLineno(), templateLoader, expectedTokenClass, t.getClass()); } }
private Parser createParser(String templateName) { URI currentUri = URI.create(filename); URI templateUri = currentUri.resolve(templateName); try { return new Parser(templateUri.toString(), templateLoader); } catch (IOException e) { throw new JadeParserException( filename, lexer.getLineno(), templateLoader, "the template [" + templateName + "] could not be opened\n" + e.getMessage()); } }
private Node block() { BlockNode block = new BlockNode(); block.setLineNumber(lexer.getLineno()); block.setFileName(filename); expect(Indent.class); while (!(peek() instanceof Outdent) && !(peek() instanceof Eos)) { if (peek() instanceof Newline) { nextToken(); } else { Node parseExpr = this.parseExpr(); if (parseExpr != null) { block.push(parseExpr); } } } if (peek() instanceof Outdent) { expect(Outdent.class); } return block; }
public Node parse() { BlockNode block = new BlockNode(); block.setLineNumber(lexer.getLineno()); block.setFileName(filename); while (!(peek() instanceof Eos)) { if (peek() instanceof Newline) { nextToken(); } else { Node expr = parseExpr(); if (expr != null) { block.push(expr); } } } if (extending != null) { getContexts().push(extending); Node rootNode = extending.parse(); getContexts().pop(); return rootNode; } return block; }
private int line() { return lexer.getLineno(); }
private Token nextToken() { return lexer.advance(); }
private void skip(int n) { while (n > 0) { lexer.advance(); n = n - 1; } }
private Token lookahead(int i) { return lexer.lookahead(i); }
private Node parseTag() { // ast-filter look-ahead int i = 2; if (lookahead(i) instanceof Attribute) { i++; } if (lookahead(i) instanceof Colon) { i++; if (lookahead(i) instanceof Indent) { return this.parseASTFilter(); } } Token token = nextToken(); String name = token.getValue(); TagNode tagNode = new TagNode(); tagNode.setLineNumber(lexer.getLineno()); tagNode.setFileName(filename); tagNode.setName(name); tagNode.setValue(name); while (true) { Token incomingToken = peek(); if (incomingToken instanceof CssId) { Token tok = nextToken(); tagNode.addAttribute("id", tok.getValue()); continue; } else if (incomingToken instanceof CssClass) { Token tok = nextToken(); tagNode.addAttribute("class", tok.getValue()); continue; } else if (incomingToken instanceof Attribute) { Attribute tok = (Attribute) nextToken(); tagNode.addAttributes(tok.getAttributes()); continue; } else { break; } } // check immediate '.' boolean dot = false; if (peek() instanceof Dot) { dot = true; tagNode.setTextOnly(true); nextToken(); } // (text | code | ':')? if (peek() instanceof Text) { tagNode.setTextNode(parseText()); } else if (peek() instanceof Expression) { tagNode.setCodeNode(parseCode()); } else if (peek() instanceof Colon) { Token next = nextToken(); BlockNode block = new BlockNode(); block.setLineNumber(next.getLineNumber()); block.setFileName(filename); tagNode.setBlock(block); block.push(parseExpr()); } // newline* while (peek() instanceof Newline) { nextToken(); } if (!tagNode.isTextOnly()) { if (Arrays.asList(textOnlyTags).contains(tagNode.getName())) { tagNode.setTextOnly(true); } } // script special-case if ("script".equals(tagNode.getName())) { String type = tagNode.getAttribute("type"); if (!dot && StringUtils.isNotBlank(type)) { String cleanType = type.replaceAll("^['\"]|['\"]$", ""); if (!"text/javascript".equals(cleanType)) { tagNode.setTextOnly(false); } } } if (peek() instanceof Indent) { if (tagNode.isTextOnly()) { lexer.setPipeless(true); tagNode.setTextNode(parseTextBlock()); lexer.setPipeless(false); } else { Node blockNode = block(); if (tagNode.hasBlock()) { tagNode.getBlock().getNodes().addAll(blockNode.getNodes()); } else { tagNode.setBlock(blockNode); } } } return tagNode; }