org.sonar.css.parser.less.LessGrammar Maven / Gradle / Ivy
/*
* SonarQube CSS / SCSS / Less Analyzer
* Copyright (C) 2013-2016 Tamas Kende and David RACODON
* mailto: [email protected] and [email protected]
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.css.parser.less;
import com.sonar.sslr.api.typed.GrammarBuilder;
import org.sonar.css.parser.LexicalGrammar;
import org.sonar.css.parser.TreeFactory;
import org.sonar.css.parser.css.CssGrammar;
import org.sonar.css.tree.impl.SeparatedList;
import org.sonar.css.tree.impl.css.InternalSyntaxToken;
import org.sonar.plugins.css.api.tree.Tree;
import org.sonar.plugins.css.api.tree.css.*;
import org.sonar.plugins.css.api.tree.less.*;
/**
* Less grammar based on:
* - http://lesscss.org/features/
*/
public class LessGrammar extends CssGrammar {
public LessGrammar(GrammarBuilder b, TreeFactory f) {
super(b, f);
}
@Override
public StyleSheetTree STYLESHEET() {
return b.nonterminal(LexicalGrammar.STYLESHEET).is(
f.stylesheet(
b.optional(b.token(LexicalGrammar.BOM)),
b.zeroOrMore(
b.firstOf(
LESS_VARIABLE_DECLARATION(),
AT_RULE(),
RULESET(),
LESS_MIXIN_CALL(),
EMPTY_STATEMENT())),
b.token(LexicalGrammar.EOF)));
}
@Override
public StatementBlockTree RULESET_BLOCK() {
return b.nonterminal(LexicalGrammar.RULESET_BLOCK).is(
f.rulesetBlock(STATEMENT_BLOCK()));
}
@Override
public StatementBlockTree AT_RULE_BLOCK() {
return b.nonterminal(LexicalGrammar.AT_RULE_BLOCK).is(
f.atRuleBlock(STATEMENT_BLOCK()));
}
public StatementBlockTree STATEMENT_BLOCK() {
return b.nonterminal(LexicalGrammar.STATEMENT_BLOCK).is(
f.statementBlock(
b.token(LexicalGrammar.OPEN_CURLY_BRACE),
b.zeroOrMore(
b.firstOf(
DECLARATION(),
AT_RULE(),
RULESET(),
LESS_MIXIN_CALL(),
EMPTY_STATEMENT())),
b.token(LexicalGrammar.CLOSE_CURLY_BRACE)));
}
@Override
public Tree ANY() {
return b.nonterminal().is(
b.firstOf(
VALUE_COMMA_SEPARATED_LIST(),
URI(),
FUNCTION(),
PSEUDO_SELECTOR(),
PARENTHESIS_BLOCK(),
BRACKET_BLOCK(),
PERCENTAGE(),
DIMENSION(),
NUMBER(),
STRING(),
HASH(),
UNICODE_RANGE(),
LESS_OPERATOR(),
IDENTIFIER(),
IMPORTANT_FLAG(),
LESS_ESCAPING(),
LESS_INTERPOLATED_IDENTIFIER(),
LESS_VARIABLE(),
b.token(LexicalGrammar.COLON),
DELIMITER()));
}
@Override
public Tree ANY_WITHOUT_COMMA_SEPARATED_LIST() {
return b.nonterminal().is(
b.firstOf(
URI(),
FUNCTION(),
PSEUDO_SELECTOR(),
PARENTHESIS_BLOCK(),
BRACKET_BLOCK(),
PERCENTAGE(),
DIMENSION(),
NUMBER(),
STRING(),
HASH(),
UNICODE_RANGE(),
LESS_OPERATOR(),
IDENTIFIER(),
IMPORTANT_FLAG(),
LESS_ESCAPING(),
LESS_INTERPOLATED_IDENTIFIER(),
LESS_VARIABLE(),
b.token(LexicalGrammar.COLON),
DELIMITER()));
}
@Override
public DeclarationTree DECLARATION() {
return b.nonterminal(LexicalGrammar.DECLARATION).is(
b.firstOf(
LESS_VARIABLE_DECLARATION(),
CSS_DECLARATION()));
}
@Override
public PropertyTree PROPERTY() {
return b.nonterminal(LexicalGrammar.PROPERTY).is(
f.property(
b.firstOf(
LESS_INTERPOLATED_IDENTIFIER(),
IDENTIFIER()),
b.optional(b.token(LexicalGrammar.LESS_MERGE))));
}
@Override
public SelectorTree SELECTOR() {
return b.nonterminal(LexicalGrammar.SELECTOR).is(
f.lessSelector(
b.optional(LESS_PARENT_SELECTOR_COMBINATOR()),
COMPOUND_SELECTOR_COMBINATION_LIST(),
b.optional(LESS_EXTEND()),
b.optional(LESS_MIXIN_PARAMETERS()),
b.optional(LESS_MIXIN_GUARD())));
}
public SelectorCombinatorTree LESS_PARENT_SELECTOR_COMBINATOR() {
return b.nonterminal(LexicalGrammar.LESS_PARENT_SELECTOR_COMBINATOR).is(
f.lessParentSelectorCombinator(
b.firstOf(
b.token(LexicalGrammar.CHILD_COMBINATOR),
b.token(LexicalGrammar.NEXT_SIBLING_COMBINATOR),
b.token(LexicalGrammar.FOLLOWING_SIBLING_COMBINATOR))));
}
@Override
public CompoundSelectorTree COMPOUND_SELECTOR() {
return b.nonterminal(LexicalGrammar.COMPOUND_SELECTOR).is(
f.compoundSelector(
b.oneOrMore(
b.firstOf(
LESS_PARENT_SELECTOR(),
SIMPLE_CSS_SELECTOR()))));
}
@Override
public ClassSelectorTree CLASS_SELECTOR() {
return b.nonterminal(LexicalGrammar.CLASS_SELECTOR).is(
f.classSelector(
b.token(LexicalGrammar.DOT),
b.firstOf(
LESS_INTERPOLATED_IDENTIFIER_NO_WS(),
IDENTIFIER_NO_WS())));
}
@Override
public TypeSelectorTree TYPE_SELECTOR() {
return b.nonterminal(LexicalGrammar.TYPE_SELECTOR).is(
f.typeSelector(
b.optional(NAMESPACE()),
b.firstOf(
LESS_INTERPOLATED_IDENTIFIER_NO_WS(),
LESS_IDENTIFIER_NO_WS_NOR_WHEN())));
}
@Override
public IdSelectorTree ID_SELECTOR() {
return b.nonterminal(LexicalGrammar.ID_SELECTOR).is(
f.idSelector(
b.token(LexicalGrammar.HASH_SYMBOL_NO_WS),
b.firstOf(
LESS_INTERPOLATED_IDENTIFIER_NO_WS(),
IDENTIFIER_NO_WS())));
}
@Override
public AttributeSelectorTree ATTRIBUTE_SELECTOR() {
return b.nonterminal(LexicalGrammar.ATTRIBUTE_SELECTOR).is(
b.firstOf(
f.attributeSelector(
b.token(LexicalGrammar.OPEN_BRACKET_NO_WS),
b.firstOf(
LESS_INTERPOLATED_IDENTIFIER(),
IDENTIFIER()),
b.optional(ATTRIBUTE_MATCHER_EXPRESSION()),
b.token(LexicalGrammar.CLOSE_BRACKET)),
f.attributeSelector(
b.token(LexicalGrammar.OPEN_BRACKET_NO_WS),
b.token(LexicalGrammar.SPACING),
NAMESPACE(),
b.firstOf(
LESS_INTERPOLATED_IDENTIFIER_NO_WS(),
IDENTIFIER_NO_WS()),
b.optional(ATTRIBUTE_MATCHER_EXPRESSION()),
b.token(LexicalGrammar.CLOSE_BRACKET))));
}
@Override
public AttributeMatcherExpressionTree ATTRIBUTE_MATCHER_EXPRESSION() {
return b.nonterminal(LexicalGrammar.ATTRIBUTE_MATCHER_EXPRESSION).is(
f.attributeMatcherExpression(
ATTRIBUTE_MATCHER(),
b.firstOf(
STRING(),
b.firstOf(
LESS_INTERPOLATED_IDENTIFIER(),
IDENTIFIER())),
b.optional(CASE_INSENSITIVE_FLAG())));
}
@Override
public PseudoIdentifierTree PSEUDO_IDENTIFIER() {
return b.nonterminal(LexicalGrammar.PSEUDO_IDENTIFIER).is(
f.pseudoIdentifier(
b.token(LexicalGrammar.PSEUDO_PREFIX),
b.firstOf(
LESS_INTERPOLATED_IDENTIFIER_NO_WS(),
IDENTIFIER_NO_WS())));
}
public LessParentSelectorTree LESS_PARENT_SELECTOR() {
return b.nonterminal(LexicalGrammar.LESS_PARENT_SELECTOR).is(
f.lessParentSelector(b.token(LexicalGrammar.LESS_PARENT_SELECTOR_KEYWORD)));
}
public LessVariableDeclarationTree LESS_VARIABLE_DECLARATION() {
return b.nonterminal(LexicalGrammar.LESS_VARIABLE_DECLARATION).is(
f.lessVariableDeclaration(
LESS_VARIABLE(),
b.token(LexicalGrammar.COLON),
DECLARATION_VALUE(),
b.optional(b.token(LexicalGrammar.SEMICOLON))));
}
public LessVariableTree LESS_VARIABLE() {
return b.nonterminal(LexicalGrammar.LESS_VARIABLE).is(
f.lessVariable(
b.token(LexicalGrammar.LESS_VARIABLE_PREFIX),
IDENTIFIER_NO_WS()));
}
public LessExtendTree LESS_EXTEND() {
return b.nonterminal(LexicalGrammar.LESS_EXTEND).is(
f.lessExtend(
b.token(LexicalGrammar.LESS_EXTEND_PREFIX),
b.token(LexicalGrammar.OPEN_PARENTHESIS_NO_WS),
b.oneOrMore(SIMPLE_VALUE()),
b.token(LexicalGrammar.CLOSE_PARENTHESIS)));
}
public LessMixinCallTree LESS_MIXIN_CALL() {
return b.nonterminal(LexicalGrammar.LESS_MIXIN_CALL).is(
f.lessMixinCall(
b.optional(LESS_PARENT_SELECTOR_COMBINATOR()),
b.optional(b.token(LexicalGrammar.SPACING)),
SELECTOR(),
b.optional(IMPORTANT_FLAG()),
b.optional(b.token(LexicalGrammar.SEMICOLON))));
}
public LessMixinGuardTree LESS_MIXIN_GUARD() {
return b.nonterminal(LexicalGrammar.LESS_MIXIN_GUARD).is(
f.lessMixinGuard(
b.token(LexicalGrammar.LESS_MIXIN_GUARD_WHEN),
b.optional(b.token(LexicalGrammar.LESS_MIXIN_GUARD_NOT)),
LESS_MIXIN_GUARD_CONDITION_LIST()));
}
public SeparatedList LESS_MIXIN_GUARD_CONDITION_LIST() {
return b.>nonterminal().is(
f.lessMixinGuardConditionList(
PARENTHESIS_BLOCK(),
b.zeroOrMore(
f.newTuple2(
b.firstOf(
b.token(LexicalGrammar.LESS_MIXIN_GUARD_AND),
b.token(LexicalGrammar.LESS_MIXIN_GUARD_OR)),
PARENTHESIS_BLOCK()))));
}
public LessMixinParametersTree LESS_MIXIN_PARAMETERS() {
return b.nonterminal(LexicalGrammar.LESS_MIXIN_PARAMETERS).is(
f.lessMixinParameters(
b.token(LexicalGrammar.OPEN_PARENTHESIS),
b.optional(LESS_MIXIN_PARAMETER_LIST()),
b.token(LexicalGrammar.CLOSE_PARENTHESIS)));
}
public SeparatedList LESS_MIXIN_PARAMETER_LIST() {
return b.>nonterminal().is(
f.lessMixinParameterList(
LESS_MIXIN_PARAMETER(),
b.zeroOrMore(
f.newTuple3(
b.firstOf(
b.token(LexicalGrammar.COMMA),
b.token(LexicalGrammar.SEMICOLON)),
LESS_MIXIN_PARAMETER())),
b.optional(
b.firstOf(
b.token(LexicalGrammar.COMMA),
b.token(LexicalGrammar.SEMICOLON)))));
}
public LessMixinParameterTree LESS_MIXIN_PARAMETER() {
return b.nonterminal(LexicalGrammar.LESS_MIXIN_PARAMETER).is(
b.firstOf(
f.lessMixinParameter(
LESS_VARIABLE(),
b.optional(b.token(LexicalGrammar.COLON)),
b.optional(DECLARATION_VALUE())),
f.lessMixinParameter(DECLARATION_VALUE())));
}
public IdentifierTree LESS_INTERPOLATED_IDENTIFIER() {
return b.nonterminal(LexicalGrammar.LESS_INTERPOLATED_IDENTIFIER).is(
f.lessInterpolatedIdentifier(b.token(LexicalGrammar.LESS_IDENT_INTERPOLATED_IDENTIFIER)));
}
public IdentifierTree LESS_INTERPOLATED_IDENTIFIER_NO_WS() {
return b.nonterminal(LexicalGrammar.LESS_INTERPOLATED_IDENTIFIER_NO_WS).is(
f.lessInterpolatedIdentifierNoWs(b.token(LexicalGrammar.LESS_IDENT_INTERPOLATED_IDENTIFIER_NO_WS)));
}
public IdentifierTree LESS_IDENTIFIER_NO_WS_NOR_WHEN() {
return b.nonterminal(LexicalGrammar.LESS_IDENTIFIER_NO_WS_NOR_WHEN).is(
f.lessIdentifierNoWsNorWhen(b.token(LexicalGrammar.LESS_IDENT_IDENTIFIER_NO_WS_NOR_WHEN)));
}
public LessEscapingTree LESS_ESCAPING() {
return b.nonterminal(LexicalGrammar.LESS_ESCAPING).is(
f.lessEscaping(
b.token(LexicalGrammar.LESS_ESCAPING_SYMBOL),
STRING_NO_WS()));
}
public LessOperatorTree LESS_OPERATOR() {
return b.nonterminal(LexicalGrammar.LESS_OPERATOR).is(
f.lessOperator(b.token(LexicalGrammar.LESS_OPERATOR_LITERAL)));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy