Skip to content

Commit

Permalink
Basic support for import: place import declarations on top of input file
Browse files Browse the repository at this point in the history
and print it as it is. #83 and #19
  • Loading branch information
meri committed Jan 10, 2013
1 parent a448013 commit 6014a78
Show file tree
Hide file tree
Showing 13 changed files with 287 additions and 64 deletions.
13 changes: 8 additions & 5 deletions src/main/antlr3/com/github/sommeri/less4j/core/parser/Less.g
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,6 @@ tokens {
styleSheet
@init {enterRule(retval, RULE_STYLESHEET);}
: ( a+=charSet* //the original ? was replaced by *, because it is possible (even if it makes no sense) and less.js is able to handle such situation
a+=imports*
a+=bodylist
EOF ) -> ^(STYLE_SHEET ($a)*)
;
Expand All @@ -186,7 +185,7 @@ finally { leaveRule(); }
//
imports
@init {enterRule(retval, RULE_IMPORTS);}
: IMPORT_SYM (STRING|URI) (mediaQuery (COMMA mediaQuery)*)? SEMI
: (IMPORT_SYM | IMPORT_ONCE_SYM | IMPORT_MULTIPLE_SYM)^ (term) (mediaQuery (COMMA mediaQuery)*)? SEMI!
;
finally { leaveRule(); }

Expand Down Expand Up @@ -256,6 +255,7 @@ bodyset
| keyframes
| page
| fontface
| imports
;

variabledeclaration
Expand Down Expand Up @@ -377,6 +377,7 @@ general_body
| (reusableStructure)=>a+=reusableStructure
| a+=pageMarginBox
| a+=variabledeclaration
| a+=imports
)*
(
( (declaration)=>a+=declaration RBRACE)
Expand Down Expand Up @@ -1106,7 +1107,9 @@ IDENT : '-'? NMSTART NMCHAR* ;
fragment HASH_FRAGMENT : '#' NAME ;
HASH : HASH_FRAGMENT ;

IMPORT_SYM : '@' I M P O R T ;
IMPORT_SYM : '@' I M P O R T;
IMPORT_ONCE_SYM : '@' I M P O R T MINUS O N C E;
IMPORT_MULTIPLE_SYM : '@' I M P O R T MINUS M U L T I P L E;
PAGE_SYM : '@' P A G E ;
MEDIA_SYM : '@' M E D I A ;
FONT_FACE_SYM : '@' F O N T MINUS F A C E ;
Expand Down Expand Up @@ -1195,10 +1198,10 @@ NUMBER
// url and uri.
URI : (U R L
'('
((WS)=>WS)? (URL|STRING) WS?
((WS)=>WS)? (URL) WS?
')') => (U R L
'('
((WS)=>WS)? (URL|STRING) WS?
((WS)=>WS)? (URL) WS?
')')
| U R L { $type=IDENT; }
;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package com.github.sommeri.less4j.core.ast;

public enum ASTCssNodeType {
UNKNOWN, CSS_CLASS, DECLARATION, STYLE_SHEET, RULE_SET, SELECTOR, SIMPLE_SELECTOR, PSEUDO_CLASS, PSEUDO_ELEMENT, SELECTOR_ATTRIBUTE, ID_SELECTOR, CHARSET_DECLARATION, FONT_FACE, IDENTIFIER_EXPRESSION, COMPOSED_EXPRESSION, STRING_EXPRESSION, NUMBER, COLOR_EXPRESSION, FUNCTION, MEDIA, COMMENT, DECLARATIONS_BODY, SELECTOR_OPERATOR, SELECTOR_COMBINATOR, EXPRESSION_OPERATOR, NTH, NAMED_EXPRESSION, MEDIA_QUERY, MEDIA_EXPRESSION, MEDIUM, MEDIUM_MODIFIER, MEDIUM_TYPE, MEDIUM_EX_FEATURE, VARIABLE_DECLARATION, VARIABLE, INDIRECT_VARIABLE, PARENTHESES_EXPRESSION, SIGNED_EXPRESSION, ARGUMENT_DECLARATION, MIXIN_REFERENCE, GUARD_CONDITION, COMPARISON_EXPRESSION, GUARD, NESTED_SELECTOR_APPENDER, REUSABLE_STRUCTURE, FAULTY_EXPRESSION, ESCAPED_SELECTOR, ESCAPED_VALUE, INTERPOLABLE_NAME, FIXED_NAME_PART, VARIABLE_NAME_PART, KEYFRAMES, KEYFRAMES_NAME, KEYFRAMES_BODY, REUSABLE_STRUCTURE_NAME, VIEWPORT, GENERAL_BODY, PAGE, NAME, PAGE_MA, PAGE_MARGIN_BOX
UNKNOWN, CSS_CLASS, DECLARATION, STYLE_SHEET, RULE_SET, SELECTOR, SIMPLE_SELECTOR, PSEUDO_CLASS, PSEUDO_ELEMENT, SELECTOR_ATTRIBUTE, ID_SELECTOR, CHARSET_DECLARATION, FONT_FACE, IDENTIFIER_EXPRESSION, COMPOSED_EXPRESSION, STRING_EXPRESSION, NUMBER, COLOR_EXPRESSION, FUNCTION, MEDIA, COMMENT, DECLARATIONS_BODY, SELECTOR_OPERATOR, SELECTOR_COMBINATOR, EXPRESSION_OPERATOR, NTH, NAMED_EXPRESSION, MEDIA_QUERY, MEDIA_EXPRESSION, MEDIUM, MEDIUM_MODIFIER, MEDIUM_TYPE, MEDIUM_EX_FEATURE, VARIABLE_DECLARATION, VARIABLE, INDIRECT_VARIABLE, PARENTHESES_EXPRESSION, SIGNED_EXPRESSION, ARGUMENT_DECLARATION, MIXIN_REFERENCE, GUARD_CONDITION, COMPARISON_EXPRESSION, GUARD, NESTED_SELECTOR_APPENDER, REUSABLE_STRUCTURE, FAULTY_EXPRESSION, ESCAPED_SELECTOR, ESCAPED_VALUE, INTERPOLABLE_NAME, FIXED_NAME_PART, VARIABLE_NAME_PART, KEYFRAMES, KEYFRAMES_NAME, KEYFRAMES_BODY, REUSABLE_STRUCTURE_NAME, VIEWPORT, GENERAL_BODY, PAGE, NAME, PAGE_MA, PAGE_MARGIN_BOX, IMPORT
}
76 changes: 76 additions & 0 deletions src/main/java/com/github/sommeri/less4j/core/ast/Import.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package com.github.sommeri.less4j.core.ast;

import java.util.ArrayList;
import java.util.List;

import com.github.sommeri.less4j.core.parser.HiddenTokenAwareTree;
import com.github.sommeri.less4j.utils.ArraysUtils;

public class Import extends ASTCssNode {

private ImportKind kind = ImportKind.IMPORT;
private Expression urlExpression;
private List<MediaQuery> mediums = new ArrayList<MediaQuery>();

public Import(HiddenTokenAwareTree underlyingStructure) {
super(underlyingStructure);
}

public ImportKind getKind() {
return kind;
}

public void setKind(ImportKind kind) {
this.kind = kind;
}

public Expression getUrlExpression() {
return urlExpression;
}

public void setUrlExpression(Expression urlExpression) {
this.urlExpression = urlExpression;
}

public List<MediaQuery> getMediums() {
return mediums;
}

public void setMediums(List<MediaQuery> mediums) {
this.mediums = mediums;
}

public void add(MediaQuery medium) {
mediums.add(medium);
}

@Override
public List<? extends ASTCssNode> getChilds() {
List<ASTCssNode> result = ArraysUtils.asNonNullList((ASTCssNode)urlExpression);
result.addAll(mediums);
return result;
}

@Override
public Import clone() {
Import result = (Import) super.clone();
result.urlExpression = urlExpression==null? null : urlExpression.clone();
result.mediums = ArraysUtils.deeplyClonedList(mediums);
result.configureParentToAllChilds();
return result;
}

//@Override
//public String toString() {
//}

@Override
public ASTCssNodeType getType() {
return ASTCssNodeType.IMPORT;
}

public enum ImportKind {
IMPORT, IMPORT_ONCE, IMPORT_MULTIPLE
}

}
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package com.github.sommeri.less4j.core.compiler;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import com.github.sommeri.less4j.core.ast.ASTCssNode;
import com.github.sommeri.less4j.core.ast.ASTCssNodeType;
import com.github.sommeri.less4j.core.ast.Body;
import com.github.sommeri.less4j.core.ast.Declaration;
import com.github.sommeri.less4j.core.ast.Expression;
Expand Down Expand Up @@ -34,20 +37,40 @@ public LessToCssCompiler(ProblemsHandler problemsHandler) {
public ASTCssNode compileToCss(StyleSheet less) {
ScopeExtractor scopeBuilder = new ScopeExtractor();
Scope scope = scopeBuilder.extractScope(less);

ReferencesSolver referencesSolver = new ReferencesSolver(problemsHandler);
referencesSolver.solveReferences(less, scope);

//just a safety measure
evaluateExpressions(less);
freeNestedRuleSets(less);
sortTopLevelElements(less);

return less;
}

private void sortTopLevelElements(StyleSheet less) {
Collections.sort(less.getChilds(), new Comparator<ASTCssNode>() {

@Override
public int compare(ASTCssNode first, ASTCssNode second) {
return code(first) - code(second);
}

private int code(ASTCssNode node) {
if (node.getType() == ASTCssNodeType.CHARSET_DECLARATION)
return 0;
if (node.getType() == ASTCssNodeType.IMPORT)
return 1;

return 2;
}
});
}

private void freeNestedRuleSets(Body<ASTCssNode> body) {
NestedRulesCollector nestedRulesCollector = new NestedRulesCollector();

List<? extends ASTCssNode> childs = new ArrayList<ASTCssNode>(body.getChilds());
for (ASTCssNode kid : childs) {
switch (kid.getType()) {
Expand Down
Loading

0 comments on commit 6014a78

Please sign in to comment.