private void readAttributeName(StringBuilder sb) { if (!tokenizer.current().isSymbol("]")) { if (!tokenizer.current().isIdentifier()) { tokenizer.addError(tokenizer.current(), "Unexpected token: '%s'. Expected an attribute name.", tokenizer.current().getSource()); } sb.append(tokenizer.consume().getContents()); } }
private void parseMediaQuerySelector(Section result) { // Parse a media query like @media screen and (min-width: 1200px) tokenizer.consumeExpectedKeyword(KEYWORD_MEDIA); while (true) { if (tokenizer.current().isIdentifier()) { // Handle plain identifiers like "screen" or "print" result.addMediaQuery(new Value(tokenizer.consume().getContents())); } else if (tokenizer.current().isSymbol("(")) { parseMediaQueryFilters(result); } else { return; } // We only handle "and" as conjunction between two filters if (!tokenizer.current().isIdentifier("and")) { return; } else { tokenizer.consume(); } } }
private void parseName(Mixin mixin) { if (tokenizer.current().isIdentifier()) { mixin.setName(tokenizer.consume().getContents()); } else { tokenizer.addError(tokenizer.current(), "Unexpected token: '" + tokenizer.current().getSource() + "'. Expected the name of the mixin as identifier."); } }
private boolean isAtAttribute() { // an attribute has at least to start with x: y ... if (!tokenizer.current().isIdentifier() || !tokenizer.next().isSymbol(":")) { return false; } // We have to actually search for the final ";" to determine if we're // really looking at an attribute.... int i = 2; while (true) { Token next = tokenizer.next(i); if (next.isEnd() || next.isSymbol(";")) { return true; } else if (next.isSymbol("{")) { return false; } else { i++; } } }
private List<String> parseSelector() { List<String> selector = new ArrayList<>(); parseSelectorPrefix(selector); while (tokenizer.more()) { if (tokenizer.current().isSymbol("{", ",")) { if (selector.isEmpty()) { tokenizer.addError(tokenizer.current(), "Unexpected end of CSS selector"); } return selector; } else if (tokenizer.current().isIdentifier() || tokenizer.current().isSpecialIdentifier("#", "@") || tokenizer.current().isNumber()) { StringBuilder sb = new StringBuilder(tokenizer.consume().getSource()); parseFilterInSelector(sb); parseOperatorInSelector(sb); selector.add(sb.toString()); } else if (tokenizer.current().isSymbol("&") || tokenizer.current().isSymbol("*")) { selector.add(tokenizer.consume().getTrigger()); } else if (tokenizer.current().isSymbol(">", "+", "~")) { selector.add(tokenizer.consume().getSource()); } else { tokenizer.addError(tokenizer.current(), "Unexpected Token: %s", tokenizer.consume().getSource()); } } return selector; }
private Expression parseIdentifierOrFunctionCall() { // Identifiers might contain ':' like "progid:DXImageTransform.Microsoft.gradient" StringBuilder id = new StringBuilder(); while (tokenizer.current().isIdentifier() && tokenizer.next().isSymbol(":")) { id.append(tokenizer.consume().getSource()).append(":"); tokenizer.consume(); } id.append(tokenizer.consume().getSource()); if (tokenizer.current().isSymbol("(")) { // An identifier followed by '(' is a function call... FunctionCall fun = new FunctionCall(); fun.setName(id.toString()); tokenizer.consumeExpectedSymbol("("); while (tokenizer.more() && !tokenizer.current().isSymbol(")", ";", "{", "}")) { if (tokenizer.current().isIdentifier() && tokenizer.next().isSymbol("=")) { String name = tokenizer.consume().getContents(); tokenizer.consume(); fun.addParameter(new NamedParameter(name, parseExpression(false))); } else { fun.addParameter(parseExpression(false)); } consumeExpectedComma(); } tokenizer.consumeExpectedSymbol(")"); return fun; } // Neither function or value list -> simple value return new Value(id.toString()); }
private void parseExtend(Section result) { // Parse @extend instructions like "@extend .warning" tokenizer.consumeExpectedKeyword(KEYWORD_EXTEND); if (tokenizer.current().isIdentifier() || tokenizer.current().isSpecialIdentifier("#")) { result.addExtends(tokenizer.consume().getSource()); } else { tokenizer.addError(tokenizer.current(), "Unexpected token: '" + tokenizer.current().getSource() + "'. Expected a selector to include."); } if (tokenizer.current().isSymbol(";") || !tokenizer.next().isSymbol("}")) { tokenizer.consumeExpectedSymbol(";"); } }
private void parseMediaQueryFilters(Section result) { // Handle filters like (orientation: landscape) tokenizer.consumeExpectedSymbol("("); if (tokenizer.current().isIdentifier() && tokenizer.next().isSymbol(":")) { parseMediaQueryFilter(result); while (tokenizer.next().hasContent("and")) { tokenizer.consumeExpectedSymbol(")"); tokenizer.consume(); tokenizer.consumeExpectedSymbol("("); parseMediaQueryFilter(result); } } else { tokenizer.addError(tokenizer.current(), "Unexpected symbol: '%s'. Expected an attribute filter.", tokenizer.current().getSource()); } tokenizer.consumeExpectedSymbol(")"); }
private void parseMixinSubSection(Mixin mixin) { Section subSection = new Section(); parseSectionSelector(false, subSection); tokenizer.consumeExpectedSymbol("{"); while (tokenizer.more() && !tokenizer.current().isSymbol("}")) { if (tokenizer.current().isIdentifier() && tokenizer.next().isSymbol(":")) { Attribute attr = parseAttribute(); subSection.addAttribute(attr); } else { tokenizer.addError(tokenizer.current(), "Unexpected token: '" + tokenizer.current().getSource() + "'. Expected an attribute definition"); tokenizer.consume(); } } tokenizer.consumeExpectedSymbol("}"); mixin.addSubSection(subSection); }
if (tokenizer.current().isIdentifier() || tokenizer.current().isString()) { return parseIdentifierOrFunctionCall(); if (tokenizer.current().isSymbol("!") && tokenizer.next().isIdentifier()) { tokenizer.consumeExpectedSymbol("!"); return new Value("!" + tokenizer.consume().getContents());
return call; if (tokenizer.current().isIdentifier()) { if (tokenizer.next().isSymbol("(")) { return functionCall();
return call; if (tokenizer.current().isIdentifier()) { if (tokenizer.next().isSymbol("(")) { return functionCall();
private void parseInclude(Section result) { // Take care of included mixins like "@include border(15px);" tokenizer.consumeExpectedKeyword(KEYWORD_INCLUDE); MixinReference ref = new MixinReference(); if (tokenizer.current().isIdentifier()) { ref.setName(tokenizer.consume().getContents()); } else { tokenizer.addError(tokenizer.current(), "Unexpected token: '" + tokenizer.current().getSource() + "'. Expected a mixin to use"); } if (tokenizer.current().isSymbol("(")) { tokenizer.consumeExpectedSymbol("("); // Parse parameters - be as error tolerant as possible while (tokenizer.more() && !tokenizer.current().isSymbol(")", ";", "{", "}")) { ref.addParameter(parseExpression(false)); consumeExpectedComma(); } tokenizer.consumeExpectedSymbol(")"); } if (tokenizer.current().isSymbol(";") || !tokenizer.next().isSymbol("}")) { tokenizer.consumeExpectedSymbol(";"); } if (ref.getName() != null) { result.addMixinReference(ref); } }