You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by cd...@apache.org on 2014/07/22 15:36:14 UTC
[48/51] [partial] - Migrated the directory structure to a more Maven
style structure. - Started migrating the Parser from Antlr2+3 and JFlex to
Antlr4.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/antlr2/org/apache/flex/compiler/internal/parsing/as/ImportMetadataTokenTypes.txt
----------------------------------------------------------------------
diff --git a/compiler/src/main/antlr2/org/apache/flex/compiler/internal/parsing/as/ImportMetadataTokenTypes.txt b/compiler/src/main/antlr2/org/apache/flex/compiler/internal/parsing/as/ImportMetadataTokenTypes.txt
new file mode 100644
index 0000000..478e80d
--- /dev/null
+++ b/compiler/src/main/antlr2/org/apache/flex/compiler/internal/parsing/as/ImportMetadataTokenTypes.txt
@@ -0,0 +1,68 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+Metadata // output token type name
+EOF=1
+TOKEN_NUMBER=4
+TOKEN_EQUALS=5
+TOKEN_ID=6
+TOKEN_VALUE=7
+TOKEN_STRING=8
+TOKEN_EVENT_KEYWORD = 9
+TOKEN_EFFECT_KEYWORD = 10
+TOKEN_STYLE_KEYWORD = 11
+TOKEN_ICONFILE_KEYWORD = 12
+TOKEN_ARRAYELEMENTTYPE_KEYWORD = 13
+TOKEN_DEFAULTPROPERTY_KEYWORD = 14
+TOKEN_BINDABLE_KEYWORD = 15
+TOKEN_INSTANCETYPE_KEYWORD = 16
+TOKEN_NONCOMMITTINGCHANGE_KEYWORD = 17
+TOKEN_EMBED_KEYWORD = 18
+TOKEN_INSPECTABLE_KEYWORD = 19
+TOKEN_NAME = 20
+TOKEN_OPEN_PAREN = 21
+TOKEN_CLOSE_PAREN = 22
+TOKEN_OPEN_BRACE = 23
+TOKEN_CLOSE_BRACE = 24
+TOKEN_UNKNOWN_KEYWORD = 25
+TOKEN_ATTR_NAME = 26
+TOKEN_ATTR_EVENT = 27
+TOKEN_ATTR_FORMAT = 28
+TOKEN_ATTR_TYPE = 29
+TOKEN_ATTR_ARRAY_TYPE = 30
+TOKEN_ATTR_INHERITS = 31
+TOKEN_ATTR_ENUM = 32
+TOKEN_ATTR_UNKNOWN = 33
+TOKEN_ATTR_ENV = 34
+TOKEN_ATTR_VERBOSE = 35
+TOKEN_ATTR_CATEGORY = 36
+TOKEN_ATTR_VARIABLE = 37
+TOKEN_ATTR_DEFAULT_VALUE = 38
+HIDDEN_TOKEN_NEWLINE=45
+HIDDEN_TOKEN_LETTER=46
+HIDDEN_TOKEN_DIGIT=47
+HIDDEN_TOKEN_HEX_DIGIT=48
+HIDDEN_TOKEN_ID_FIRST=49
+TOKEN_ATTR_STATES=50
+TOKEN_ATTR_IMPLEMENTATION=51
+TOKEN_ACCESSIBILITY_KEYWORD=52
+TOKEN_STATES_KEYWORD=53
+TOKEN_SKIN_STATES_KEYWORD=54
+TOKEN_ASDOC_COMMENT = 55
+TOKEN_HOST_COMPONENT_KEYWORD = 56
+TOKEN_RESOURCEBUNDLE_KEYWORD = 59
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/antlr2/org/apache/flex/compiler/internal/parsing/as/MetadataParser.g
----------------------------------------------------------------------
diff --git a/compiler/src/main/antlr2/org/apache/flex/compiler/internal/parsing/as/MetadataParser.g b/compiler/src/main/antlr2/org/apache/flex/compiler/internal/parsing/as/MetadataParser.g
new file mode 100644
index 0000000..f0c14ef
--- /dev/null
+++ b/compiler/src/main/antlr2/org/apache/flex/compiler/internal/parsing/as/MetadataParser.g
@@ -0,0 +1,397 @@
+header
+{
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.flex.compiler.internal.parsing.as;
+
+/*
+ * This file is generated from MetadataParser.g.
+ * DO NOT MAKE EDITS DIRECTLY TO THIS FILE. THEY WILL BE LOST WHEN THE FILE IS GENERATED AGAIN!!!
+ */
+
+import java.util.HashMap;
+
+import antlr.NoViableAltException;
+import antlr.ParserSharedInputState;
+import antlr.RecognitionException;
+import antlr.Token;
+import antlr.TokenBuffer;
+import antlr.TokenStream;
+import antlr.TokenStreamException;
+import antlr.collections.impl.BitSet;
+
+import org.apache.flex.compiler.internal.tree.as.IdentifierNode;
+import org.apache.flex.compiler.internal.tree.as.metadata.*;
+
+import org.apache.flex.compiler.tree.metadata.IMetaTagNode;
+import org.apache.flex.compiler.constants.IMetaAttributeConstants;
+
+}
+
+// MetadataParser parses a bunch of metadata attrs for a single node
+// (var, class, etc.) and makes up some tables of what it found.
+class MetadataParser extends Parser("org.apache.flex.compiler.internal.parsing.as.BaseMetaTagParser");
+options
+{
+ importVocab = ImportMetadata;
+ exportVocab = Metadata;
+}
+
+meta[MetaTagsNode parent]
+{
+ MetaTagNode tag = null;
+}
+ : ( asDocComment | openBrace : TOKEN_OPEN_BRACE
+ ( tag = event[parent]
+ | tag = effect[parent]
+ | tag = style[parent]
+ | tag = eventTrigger[parent]
+ | tag = typedTag[parent]
+ | tag = inspectable[parent]
+ | tag = defaultproperty[parent]
+ | tag = accessibilityClass[parent]
+ | tag = multiValue[parent]
+ | tag = skinClass[parent]
+ | tag = alternative[parent]
+ | tag = resourcebundle[parent]
+ | tag = other[parent]
+ )
+ (closeBrace : TOKEN_CLOSE_BRACE
+ | closeParen : TOKEN_CLOSE_PAREN )*
+ )*
+ {
+ afterTag(tag, openBrace, closeBrace, closeParen);
+ }
+ ;
+
+asDocComment : docToken: TOKEN_ASDOC_COMMENT
+ {
+ handleComment(docToken);
+ }
+ ;
+
+event[MetaTagsNode parent] returns [EventTagNode node]
+ {
+ node = new EventTagNode();
+ }
+ : TOKEN_EVENT_KEYWORD
+ (TOKEN_ATTR_NAME ( nameString: TOKEN_STRING { node.setName(build(nameString)); } )
+ | TOKEN_ATTR_TYPE (typeString: TOKEN_STRING { node.setEvent(typeString); } )
+ | unknownProperty[node]
+ | TOKEN_OPEN_PAREN {}
+ )*
+ {
+ applyComment(node);
+ parent.addTag(node);
+ return node;
+ }
+ ;
+
+effect[MetaTagsNode parent] returns [EffectTagNode node]
+ {
+ node = new EffectTagNode();
+ }
+ : TOKEN_EFFECT_KEYWORD
+ (TOKEN_ATTR_NAME ( nameString: TOKEN_STRING { node.setName(build(nameString)); } )
+ | TOKEN_ATTR_EVENT (typeString: TOKEN_STRING { node.setEvent(build(typeString)); } )
+ | unknownProperty[node]
+ | TOKEN_OPEN_PAREN {}
+ )*
+ {
+
+ applyComment(node);
+ parent.addTag(node);
+
+ }
+ ;
+
+style[MetaTagsNode parent] returns [StyleTagNode node]
+ {
+ node = new StyleTagNode();
+ }
+ : TOKEN_STYLE_KEYWORD
+ (TOKEN_ATTR_NAME ( nameString: TOKEN_STRING { node.setName(build(nameString)); } )
+ | TOKEN_ATTR_TYPE ( typeString: TOKEN_STRING { node.setType(typeString); } )
+ | TOKEN_ATTR_ARRAY_TYPE ( arrayTypeToken: TOKEN_STRING { node.setArrayType(build(arrayTypeToken)); } )
+ | TOKEN_ATTR_INHERITS ( boolType: TOKEN_STRING { node.setIsInheritable(getText(boolType)); } )
+ | TOKEN_ATTR_FORMAT ( formatToken: TOKEN_STRING { node.setFormat(getText(formatToken).trim()); } )
+ | TOKEN_ATTR_ENUM ( valuesToken : TOKEN_STRING { node.parseValues(getText(valuesToken).trim()); } )
+ | TOKEN_ATTR_STATES ( statesToken : TOKEN_STRING { node.parseStates(getText(statesToken).trim()); } )
+ | unknownProperty[node]
+ | TOKEN_OPEN_PAREN {}
+ )*
+ {
+ applyComment(node);
+ parent.addTag(node);
+ }
+ ;
+
+inspectable[MetaTagsNode parent] returns [InspectableTagNode node]
+ {
+ IdentifierNode type = null;
+ IdentifierNode var = null;
+ IdentifierNode arrayType = null;
+ node = new InspectableTagNode();
+ resetComments(node.getTagName());
+ }
+
+ : TOKEN_INSPECTABLE_KEYWORD
+ (TOKEN_ATTR_NAME ( nameToken: TOKEN_STRING { node.setName( getText(nameToken).trim() ); } )
+ | TOKEN_ATTR_ARRAY_TYPE ( atypeToken : TOKEN_STRING { node.setArrayType(build(atypeToken)); } )
+ | TOKEN_ATTR_TYPE ( typeToken : TOKEN_STRING { node.setType(typeToken); } )
+ | TOKEN_ATTR_VARIABLE ( varToken : TOKEN_STRING { node.setVariable(build(varToken)); } )
+ | TOKEN_ATTR_FORMAT ( formatToken : TOKEN_STRING { node.setFormat( getText(formatToken).trim() ); } )
+ | TOKEN_ATTR_ENUM ( valuesToken : TOKEN_STRING { node.parseValues( getText(valuesToken).trim() ); } )
+ | TOKEN_ATTR_CATEGORY ( catToken : TOKEN_STRING { node.setCategory( getText(catToken).trim()); } )
+ | TOKEN_ATTR_DEFAULT_VALUE ( defaultToken : TOKEN_STRING { node.setDefaultValue( getText(defaultToken).trim()); } )
+ | TOKEN_ATTR_VERBOSE ( verToken : TOKEN_STRING { node.setVerbose(getText(verToken).trim()); } )
+ | TOKEN_ATTR_ENV ( envToken : TOKEN_STRING {node.setEnvironment(getText(envToken).trim()); } )
+ | unknownProperty[node]
+ | TOKEN_OPEN_PAREN {}
+ )*
+ {
+ parent.addTag(node);
+ }
+ ;
+
+eventTrigger[MetaTagsNode parent] returns [EventTriggerTagNode node]
+ {
+ node = null;
+ IdentifierNode event = null;
+ String name = null;
+ }
+ : ( name = eventTriggerSet) {
+ resetComments(name);
+ node = new EventTriggerTagNode(name);
+ }
+ (TOKEN_ATTR_EVENT (eventToken: TOKEN_STRING { event = build(eventToken); if(event != null) { node.setEventName(event); }} )
+ | unknownProperty[node]
+ | TOKEN_OPEN_PAREN {}
+ )*
+ {
+ parent.addTag(node);
+ }
+ ;
+
+eventTriggerSet returns [String value]
+ {
+ value = null;
+ }
+ : bk : TOKEN_BINDABLE_KEYWORD
+ {
+ value = bk.getText();
+ }
+ | nck : TOKEN_NONCOMMITTINGCHANGE_KEYWORD
+ {
+ value = nck.getText();
+ }
+ ;
+
+
+typedTag[MetaTagsNode parent] returns [TypedTagNode node]
+ {
+ node = null;
+ IdentifierNode type = null;
+ String name = null;
+ }
+ : (name = typedTagSet)
+ {
+ node = new TypedTagNode(name);
+ resetComments(name);
+ }
+ ( typeToken:TOKEN_STRING
+ { node.setTypeName(null, typeToken); }
+ | TOKEN_OPEN_PAREN {})*
+ {
+ parent.addTag(node);
+ }
+ ;
+
+skinClass[MetaTagsNode parent] returns [SkinClassTagNode node]
+ {
+ node = null;
+ IdentifierNode type = null;
+ String name = null;
+ node = new SkinClassTagNode();
+ resetComments(node.getTagName());
+ }
+ : TOKEN_SKINCLASS_KEYWORD
+ ( TOKEN_ATTR_TYPE typeToken:TOKEN_STRING
+ { node.setTypeName(IMetaAttributeConstants.NAME_EVENT_TYPE, typeToken); }
+ | unknownProperty[node]
+ | TOKEN_OPEN_PAREN {}
+ )*
+ {
+ parent.addTag(node);
+ }
+ ;
+
+alternative[MetaTagsNode parent] returns [AlternativeTagNode node]
+ {
+ node = null;
+ IdentifierNode type = null;
+ String name = null;
+ node = new AlternativeTagNode();
+ resetComments(node.getTagName());
+ }
+ : TOKEN_ALTERNATIVE_KEYWORD
+ ( TOKEN_ATTR_TYPE typeToken:TOKEN_STRING
+ { node.setTypeName(IMetaAttributeConstants.NAME_ALTERNATIVE_REPLACEMENT, typeToken); }
+ | unknownProperty[node]
+ | TOKEN_OPEN_PAREN {}
+ )*
+ {
+ parent.addTag(node);
+ }
+ ;
+
+typedTagSet returns [String value]
+ {
+ value = null;
+ }
+ : ik : TOKEN_INSTANCETYPE_KEYWORD
+ {
+ value = ik.getText();
+ }
+ | hck : TOKEN_HOST_COMPONENT_KEYWORD
+ {
+ value = hck.getText();
+ }
+ | aek : TOKEN_ARRAYELEMENTTYPE_KEYWORD
+ {
+ value = aek.getText();
+ }
+ ;
+
+multiValue[MetaTagsNode parent] returns [MultiValueMetaTagNode node]
+ {
+ String state = null;
+ node = null;
+ String name = null;
+ }
+ : (name = mvSet)
+ {
+ node = new MultiValueMetaTagNode(name);
+ resetComments(name);
+ }
+ (stateToken: TOKEN_STRING { state = getText(stateToken); if(state != null) { node.addValue(state); state = null;}}
+ | TOKEN_OPEN_PAREN {})*
+ {
+ parent.addTag(node);
+ }
+ ;
+
+mvSet returns [String value]
+ {
+ value = null;
+ }
+ : bk : TOKEN_STATES_KEYWORD
+ {
+ value = bk.getText();
+ }
+ | nck : TOKEN_SKIN_STATES_KEYWORD
+ {
+ value = nck.getText();
+ }
+ ;
+
+accessibilityClass[MetaTagsNode parent] returns [AccessibilityTagNode node]
+ {
+ IdentifierNode type = null;
+ IdentifierNode name = null;
+ node = new AccessibilityTagNode();
+ resetComments(node.getTagName());
+ }
+ : TOKEN_ACCESSIBILITY_KEYWORD
+ (TOKEN_ATTR_IMPLEMENTATION nameString:TOKEN_STRING
+ { node.setTypeName(IMetaAttributeConstants.NAME_ACCESSIBILITY_IMPLEMENTATION, nameString);}
+ | TOKEN_OPEN_PAREN {})*
+ { parent.addTag(node); }
+ ;
+
+
+defaultproperty[MetaTagsNode parent] returns [DefaultPropertyTagNode node]
+ {
+ IdentifierNode type = null;
+ node = new DefaultPropertyTagNode();
+ resetComments(node.getTagName());
+ }
+ : TOKEN_DEFAULTPROPERTY_KEYWORD
+ (typeToken: TOKEN_STRING { type = build(typeToken); if(type != null) { node.setPropertyNameNode(type); }}
+ | TOKEN_OPEN_PAREN {})*
+ {
+ parent.addTag(node);
+ }
+ ;
+
+resourcebundle[MetaTagsNode parent] returns [ResourceBundleTagNode node]
+ {
+ IdentifierNode bundleNameNode = null;
+ node = new ResourceBundleTagNode();
+ resetComments(node.getTagName());
+ }
+ : TOKEN_RESOURCEBUNDLE_KEYWORD
+ ( {LA(1) == TOKEN_STRING}? bundleToken:TOKEN_STRING { bundleNameNode = build(bundleToken); if(bundleNameNode != null) { node.setBundleNameNode(bundleNameNode); }}
+ | unknownProperty[node]
+ | unknownTypeAttribute[node]
+ | TOKEN_OPEN_PAREN {})*
+ {
+ parent.addTag(node);
+ }
+ ;
+
+unknownTypeAttribute[MetaTagNode node]
+ : (TOKEN_ATTR_TYPE typeToken:TOKEN_STRING)
+ {
+ final String val = typeToken.getText();
+ if(val != null)
+ {
+ node.addToMap(IMetaAttributeConstants.NAME_EVENT_TYPE, val);
+ }
+ }
+ ;
+
+other[MetaTagsNode parent] returns [MetaTagNode node]
+ {
+ String name = "";
+ node = null;
+ }
+ : keyWord : TOKEN_UNKNOWN_KEYWORD
+ { name = getText(keyWord); node = new BasicMetaTagNode(name); resetComments(name); }
+ ( unknownProperty[node]
+ | TOKEN_OPEN_PAREN {}
+ )*
+ {
+ parent.addTag(node);
+ }
+
+ ;
+
+unknownProperty[MetaTagNode node]
+ {
+ String attr = null;
+ }
+ :( attrName:TOKEN_ATTR_UNKNOWN
+ { attr = getText(attrName); }
+ )?
+
+ stringVal:TOKEN_STRING
+ { node.addToMap(attr, getText(stringVal)); }
+ ;
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/antlr3/org/apache/flex/compiler/internal/css/CSS.g
----------------------------------------------------------------------
diff --git a/compiler/src/main/antlr3/org/apache/flex/compiler/internal/css/CSS.g b/compiler/src/main/antlr3/org/apache/flex/compiler/internal/css/CSS.g
new file mode 100644
index 0000000..074bff3
--- /dev/null
+++ b/compiler/src/main/antlr3/org/apache/flex/compiler/internal/css/CSS.g
@@ -0,0 +1,520 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ * This is a grammar for advanced CSS in Flex. It parses the CSS document and
+ * generate DOM objects.
+ */
+grammar CSS;
+
+options
+{
+ language = Java;
+ output = AST;
+ k = 2;
+}
+
+tokens
+{
+ I_RULES; I_MEDIUM_CONDITIONS; I_DECL; I_RULE; I_SELECTOR_GROUP; I_SELECTOR;
+ I_SIMPLE_SELECTOR; I_ARRAY;
+}
+
+@header
+{
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.flex.compiler.internal.css;
+
+import java.util.Map;
+import java.util.HashMap;
+import org.apache.flex.compiler.problems.CSSParserProblem;
+}
+
+@lexer::header
+{
+package org.apache.flex.compiler.internal.css;
+
+import org.apache.flex.compiler.problems.CSSParserProblem;
+}
+
+@lexer::members
+{
+
+/**
+ * Lexer problems.
+ */
+protected List<CSSParserProblem> problems = new ArrayList<CSSParserProblem>();
+
+/**
+ * Collect lexer problems.
+ */
+@Override
+public void displayRecognitionError(String[] tokenNames, RecognitionException e)
+{
+ problems.add(CSSParserProblem.create(this, tokenNames, e));
+}
+}
+
+@members
+{
+
+/**
+ * Parser problems.
+ */
+protected List<CSSParserProblem> problems = new ArrayList<CSSParserProblem>();
+
+/**
+ * Collect parser problems.
+ */
+@Override
+public void displayRecognitionError(String[] tokenNames, RecognitionException e)
+{
+ problems.add(CSSParserProblem.create(this, tokenNames, e));
+}
+
+/**
+ * Check if the cursor is at the end of a simple selector.
+ */
+private final boolean endOfSimpleSelector()
+{
+ final CommonToken nextToken = (CommonToken) getTokenStream().LT(1);
+ if (nextToken == null)
+ return true;
+
+ // Check if there's white space between the previous token and the next token.
+ final CommonToken lastToken = (CommonToken) getTokenStream().LT(-1);
+ if (lastToken != null && nextToken != null)
+ {
+ final int lastStop = lastToken.getStopIndex();
+ final int nextStart = nextToken.getStartIndex();
+ if (lastStop + 1 < nextStart)
+ {
+ return true;
+ }
+ }
+
+ // If the next token is "{" or ",", it's also end of a selector.
+ final int nextType = nextToken.getType();
+ if (nextType == BLOCK_OPEN || nextType == COMMA)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+}
+
+/**
+ * Root rule for a CSS file.
+ */
+stylesheet
+ : ( namespaceStatement | fontFace | mediaQuery | ruleset )*
+ ;
+
+/**
+ * This rule matches an "@namespace" statement.
+ *
+ * For example, declaring a namespace prefix:
+ * @namespace mx "library://ns.adobe.com/flex/mx";
+ *
+ * Declaring the default namespace:
+ * @namespace "library://ns.adobe.com/flex/spark";
+ */
+namespaceStatement
+ : AT_NAMESPACE ID? STRING SEMI_COLONS
+ -> ^(AT_NAMESPACE ID? STRING)
+ ;
+
+/**
+ * This rule matches a media query block.
+ *
+ * For example:
+ * @media all { ... }
+ *
+ * A media query block can have one or many rulesets inside.
+ */
+mediaQuery
+ : AT_MEDIA medium BLOCK_OPEN ruleset* BLOCK_END
+ -> ^(AT_MEDIA medium ruleset*)
+ ;
+
+/**
+ * This rule matches the actual Flex media query conditions.
+ * For example: (application-dpi: 240) and (os-platform: "Android")
+ */
+medium
+ : mediumCondition
+ (
+ // Flex only support "and" at the momement. (Shaoting)
+ 'and'
+ mediumCondition
+ )*
+ -> ^(I_MEDIUM_CONDITIONS mediumCondition*)
+ ;
+
+/**
+ * This rule matches a media query condition expression. It is either a
+ * word (like "all", "screen") or an expression like "(....)".
+ */
+mediumCondition
+ : ID
+ | ARGUMENTS
+ ;
+
+/**
+ * For example:
+ *
+ * @font-face {
+ * src: url("../assets/MyriadWebPro.ttf");
+ * fontFamily: myFontFamily;
+ * advancedAntiAliasing: true;
+ * }
+ *
+ * @see http://livedocs.adobe.com/flex/3/html/help.html?content=fonts_04.html
+ */
+fontFace
+ : AT_FONT_FACE declarationsBlock -> ^(AT_FONT_FACE declarationsBlock)
+ ;
+
+/**
+ * This rule matches a CSS Ruleset.
+ */
+ruleset
+ : selectorGroup declarationsBlock
+ -> ^(I_RULE selectorGroup declarationsBlock)
+ ;
+
+/**
+ * This rule matches a group of comma-separated selectors.
+ */
+selectorGroup
+ : compoundSelector ( COMMA compoundSelector )*
+ -> ^(I_SELECTOR_GROUP compoundSelector+)
+ ;
+
+/**
+ * Compound selector is a chain of simple selectors connected by combinators.
+ * Each compound selector has one "subject", which is the element name of the
+ * right most simple selector in the chain.
+ *
+ * Currently, only descendant combinator (space) is supported.
+ * If we need to support combinators, add the terminals in this production.
+ *
+ * For example:
+ * s|VBox s|HBox.content s|Button
+ */
+compoundSelector
+@init
+{
+ final List<Object> simpleSelectorNodeList = new ArrayList<Object>();
+ Object currentSimpleSelectorNode = adaptor.create(I_SIMPLE_SELECTOR, "I_SIMPLE_SELECTOR");
+ Token simpleSelectorStartToken = null;
+ Token simpleSelectorStopToken = null;
+}
+@after
+{
+ for(final Object simpleSelectorNode : simpleSelectorNodeList)
+ adaptor.addChild($compoundSelector.tree, simpleSelectorNode);
+}
+ : ( l=simpleSelectorFraction
+ {
+ // expand token range of the current simple selector
+ if (simpleSelectorStartToken == null)
+ simpleSelectorStartToken = $l.start;
+ simpleSelectorStopToken = $l.stop;
+
+ adaptor.addChild(currentSimpleSelectorNode, $l.tree);
+
+ if (endOfSimpleSelector())
+ {
+ adaptor.setTokenBoundaries(
+ currentSimpleSelectorNode,
+ simpleSelectorStartToken,
+ simpleSelectorStopToken);
+ simpleSelectorNodeList.add(currentSimpleSelectorNode);
+
+ simpleSelectorStartToken = null;
+ simpleSelectorStopToken = null;
+
+ currentSimpleSelectorNode = adaptor.create(I_SIMPLE_SELECTOR, "I_SIMPLE_SELECTOR");
+ }
+ }
+ )+
+ -> ^(I_SELECTOR)
+ // Tree nodes for simple selectors are added in the @after block.
+ ;
+
+/**
+ * A compound selector consists of one or many simple selectors.
+ * This rule matches a fraction of a simple selector.
+ *
+ * s|HBox s|Button.confirm #activeLabel, <-- compound selector
+ * s|HBox <-- simple selector
+ * s|Button.confirm <-- simple selector
+ * #activeLabel <-- simple selector
+ *
+ * This rule will match each of the following 4 fractions:
+ *
+ * [s|HBox] [s|Button] [.confirm] [#activeLabel]
+ *
+ * As you can see, the parse tree isn't aware of the start and end of a simple
+ * selector. This is because white spaces have been ignored so that the parser
+ * can't distinguish between the following input:
+ *
+ * s|Button.rounded .labelText <-- 2 simple selectors
+ * s|Button.rounded.labelText <-- 1 simple selector
+ *
+ * As a result, this rule could match only part of a simple selector, because
+ * the conditions were broken into multiple tokens.
+ */
+simpleSelectorFraction
+ : element
+ | condition
+ ;
+
+/**
+ * This rule matches a condition selector.
+ * For example: ".styleName", "#loginButton", ":up"
+ */
+condition
+ : ( DOT^ ID
+ | HASH_WORD
+ | COLON^ ID
+ )
+ ;
+
+/**
+ * This rule matches an element name with or without namespace prefix. It also
+ * matches the special "any" element "*".
+ * For example: "s|Panel", "Label", "*"
+ */
+element
+ : ID PIPE^ ID
+ | ID
+ | STAR
+ ;
+
+/**
+ * This rule matches a declarations block.
+ * For example:
+ * { font-size:12; font-family: "sans"; }
+ */
+declarationsBlock
+ : BLOCK_OPEN
+ (
+ SEMI_COLONS? // multiple semi-colons are legal
+ declaration
+ (
+ SEMI_COLONS
+ declaration
+ )*
+ SEMI_COLONS?
+ )?
+ BLOCK_END
+ -> ^(I_DECL declaration*)
+ ;
+
+/**
+ * This rule matches property declaration. The declaration is a key value pair.
+ * For example:
+ * font-size:12px
+ */
+declaration
+ : ID COLON value -> ^(COLON ID value)
+ ;
+
+/**
+ * This rule matches an array of property values or a single value.
+ * If it matches an array, the output is an I_ARRAY tree of element values.
+ * If it matches an single value, the output is a "singleValue" tree.
+ *
+ * Array example:
+ * 2.0, 2.0, 3.0, 3.0
+ * "tl", "tr", "bl", "br"
+ * #FFFFFF, #FFFFFF, #FFFFFF, #FFFFFF
+ * Verdana, Times, Sans-Serif
+ * solid 1px #666666
+ *
+ */
+value
+@init { int count = 1; }
+ : singleValue ( COMMA? singleValue { count++; } )*
+ -> {count > 1}? ^(I_ARRAY singleValue+)
+ -> singleValue
+ ;
+
+/**
+ * This rule matches one property value.
+ *
+ * For example:
+ * 12, 12px, 100%.
+ * #FF3322
+ * rgb(100%, 100%, 100%)
+ * ClassReference("mx.controls.Button")
+ * PropertyReference("size")
+ * Embed(source="assets/logo.png", mimeType="images/png")
+ * url("../fonts/myfont.ttf")
+ * local("My Font")
+ * "Times New Roman"
+ * italic
+ */
+singleValue
+ : NUMBER_WITH_UNIT
+ | HASH_WORD
+ | CLASS_REFERENCE ARGUMENTS
+ -> ^(CLASS_REFERENCE ARGUMENTS)
+ | PROPERTY_REFERENCE ARGUMENTS
+ -> ^(PROPERTY_REFERENCE ARGUMENTS)
+ | EMBED ARGUMENTS
+ -> ^(EMBED ARGUMENTS)
+ | URL ARGUMENTS -> ^(URL ARGUMENTS)
+ | LOCAL ARGUMENTS -> ^(LOCAL ARGUMENTS)
+ | RGB
+ | STRING
+ | ID
+ ;
+
+/* Lexer Rules */
+
+BLOCK_OPEN : '{' ;
+BLOCK_END : '}' ;
+COMMA : ',' ;
+PERCENT : '%' ;
+PIPE : '|' ;
+STAR : '*' ;
+DOT : '.' ;
+EQUALS: '=';
+AT_NAMESPACE : '@namespace' ;
+AT_MEDIA : '@media' ;
+COLON : ':' ;
+AT_FONT_FACE : '@font-face' ;
+CLASS_REFERENCE : 'ClassReference' ;
+PROPERTY_REFERENCE : 'PropertyReference' ;
+EMBED : 'Embed' ;
+URL : 'url' ;
+LOCAL : 'local' ;
+NULL : 'null' ;
+
+/**
+ * Matches a rgb definition - rgb(100%,100%,100%)
+ */
+RGB : 'rgb(' ( WS* NUMBER ( PERCENT | ) WS* ) ','
+ ( WS* NUMBER ( PERCENT | ) WS* ) ','
+ ( WS* NUMBER ( PERCENT | ) WS* )
+ ')' ;
+
+/** Arguments of a function call property value. */
+ARGUMENTS
+ : '(' ( options {greedy=false;}: . )* ')'
+ ;
+/**
+ * Match multiple semi-colons in Lexer level so that the parser can have a
+ * finite number of look ahead, instead of LL(*);
+ */
+SEMI_COLONS : ';'+ ;
+
+/**
+ * Matches either ID selector or color value. Unfortunately, these two types of
+ * tokens are ambiguous in ANTLR world.
+ */
+HASH_WORD
+ : '#' ( LETTER | DIGIT | '-' | '_' )+
+ ;
+
+ID : ( '-' | '_' )? LETTER ( LETTER | DIGIT | '-' | '_' )*
+ ;
+
+fragment
+LETTER
+ : 'a'..'z'
+ | 'A'..'Z'
+ ;
+
+/**
+ * Matches: 100, -100, +3.14, .25, -0.25, +.25
+ */
+fragment
+NUMBER
+ : ('+'|'-')?
+ ( DIGIT+ (DOT DIGIT+)?
+ | DOT DIGIT+
+ )
+ ;
+
+/**
+ * Matches a number with optinal unit string.
+ * For example:
+ * 2.5
+ * 2.5em
+ * 100%
+ *
+ * The grammar doesn't allow spaces between the number and the unit.
+ * For example: 35 em is a "NUMBER" and an "ID".
+ * Otherwise such input will be ambigiuous:
+ * font-style: bold 35 pt 25em
+ * "pt" could either be another keyword or the unit of "35".
+ */
+NUMBER_WITH_UNIT
+ : NUMBER (ID|PERCENT)?
+ ;
+
+fragment
+DIGIT
+ : '0'..'9'
+ ;
+
+COMMENT
+ : '/*' ( options {greedy=false;}: . )* '*/'
+ { $channel = HIDDEN; }
+ ;
+
+WS : ( ' ' | '\t' | '\r' | '\n' ) { $channel = HIDDEN; }
+ ;
+
+STRING
+ : STRING_QUOTE
+ ( ~( '\\' | STRING_QUOTE ) )*
+ STRING_QUOTE
+ ;
+
+fragment
+STRING_QUOTE
+ : '"'
+ | '\''
+ ;
+
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/antlr3/org/apache/flex/compiler/internal/css/CSSTree.g
----------------------------------------------------------------------
diff --git a/compiler/src/main/antlr3/org/apache/flex/compiler/internal/css/CSSTree.g b/compiler/src/main/antlr3/org/apache/flex/compiler/internal/css/CSSTree.g
new file mode 100644
index 0000000..59d241e
--- /dev/null
+++ b/compiler/src/main/antlr3/org/apache/flex/compiler/internal/css/CSSTree.g
@@ -0,0 +1,338 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ * This is a tree grammar for advanced CSS in Flex. It walks the AST generated
+ * by the CSS parser and builds CSS DOM objects.
+ */
+tree grammar CSSTree;
+
+options
+{
+ language = Java;
+ tokenVocab = CSS;
+ ASTLabelType = CommonTree;
+}
+
+@header
+{
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.flex.compiler.internal.css;
+
+import java.util.Map;
+import java.util.HashMap;
+import org.apache.flex.compiler.css.*;
+import org.apache.flex.compiler.problems.CSSParserProblem;
+
+}
+
+@members
+{
+
+/**
+ * CSS DOM object.
+ */
+protected CSSDocument model;
+
+/**
+ * Every definition object needs the token stream to compute source location.
+ */
+private final TokenStream tokenStream = getTreeNodeStream().getTokenStream();
+
+/**
+ * Tree walker problems.
+ */
+protected List<CSSParserProblem> problems = new ArrayList<CSSParserProblem>();
+
+/**
+ * Collect problems.
+ */
+@Override
+public void displayRecognitionError(String[] tokenNames, RecognitionException e)
+{
+ problems.add(CSSParserProblem.create(this, tokenNames, e));
+}
+}
+
+stylesheet
+scope
+{
+ // namespace declarations are buffered in this map
+ List<CSSNamespaceDefinition> namespaces;
+ // ruleset definitions are buffered in this list
+ List<CSSRule> rules;
+ // font-face declarations are buffered in this list
+ List<CSSFontFace> fontFaces;
+}
+@init
+{
+ $stylesheet::rules = new ArrayList<CSSRule>();
+ $stylesheet::namespaces = new ArrayList<CSSNamespaceDefinition>();
+ $stylesheet::fontFaces = new ArrayList<CSSFontFace>();
+}
+@after
+{
+ model = new CSSDocument($stylesheet::rules,
+ $stylesheet::namespaces,
+ $stylesheet::fontFaces,
+ $start,
+ tokenStream);
+}
+ : ( namespaceStatement | fontFace | mediaQuery | ruleset )*
+ ;
+
+namespaceStatement
+@after
+{
+ final CSSNamespaceDefinition ns = new CSSNamespaceDefinition(
+ $id.text, $uri.text, $start, tokenStream);
+ $stylesheet::namespaces.add(ns);
+}
+ : ^(AT_NAMESPACE id=ID? uri=STRING)
+ ;
+
+mediaQuery
+scope
+{
+ // media query condition clauses are buffered in this list
+ List<CSSMediaQueryCondition> conditions
+}
+@init
+{
+ $mediaQuery::conditions = new ArrayList<CSSMediaQueryCondition>();
+}
+ : ^(AT_MEDIA medium ruleset*)
+ ;
+
+medium
+ : ^(I_MEDIUM_CONDITIONS mediumCondition*)
+ ;
+
+mediumCondition
+@after
+{
+ $mediaQuery::conditions.add(new CSSMediaQueryCondition($start, tokenStream));
+}
+ : ID | ARGUMENTS
+ ;
+
+fontFace
+@after
+{
+ final CSSFontFace fontFace = new CSSFontFace($d.properties, $start, tokenStream);
+ $stylesheet::fontFaces.add(fontFace);
+}
+ : ^(AT_FONT_FACE d=declarationsBlock)
+ ;
+
+ruleset
+scope
+{
+ // list of subject selectors
+ List<CSSSelector> subjects
+}
+@init
+{
+ $ruleset::subjects = new ArrayList<CSSSelector>();
+}
+@after
+{
+ final List<CSSMediaQueryCondition> mediaQueryConditions;
+ if ($mediaQuery.isEmpty())
+ mediaQueryConditions = null;
+ else
+ mediaQueryConditions = $mediaQuery::conditions;
+
+ final CSSRule cssRule = new CSSRule(
+ mediaQueryConditions,
+ $ruleset::subjects,
+ $d.properties,
+ $start,
+ tokenStream);
+ $stylesheet::rules.add(cssRule);
+}
+ : ^(I_RULE selectorGroup d=declarationsBlock)
+ ;
+
+selectorGroup
+ : ^(I_SELECTOR_GROUP compoundSelector+)
+ ;
+
+compoundSelector
+@init
+{
+ final Stack<CSSSelector> simpleSelectorStack = new Stack<CSSSelector>();
+}
+@after
+{
+ $ruleset::subjects.add(simpleSelectorStack.peek());
+}
+ : ^(I_SELECTOR simpleSelector[simpleSelectorStack]+)
+ ;
+
+simpleSelector [Stack<CSSSelector> simpleSelectorStack]
+scope
+{
+ String namespace;
+ String element;
+ List<CSSSelectorCondition> conditions;
+}
+@init
+{
+ $simpleSelector::conditions = new ArrayList<CSSSelectorCondition>();
+ final CSSCombinator combinator ;
+ if (simpleSelectorStack.isEmpty())
+ combinator = null;
+ else
+ combinator = new CSSCombinator(simpleSelectorStack.peek(), CombinatorType.DESCENDANT, $start, tokenStream);
+}
+@after
+{
+ final CSSSelector simpleSelector = new CSSSelector(
+ combinator,
+ $simpleSelector::element,
+ $simpleSelector::namespace,
+ $simpleSelector::conditions,
+ $start,
+ tokenStream);
+ simpleSelectorStack.push(simpleSelector);
+}
+ : ^(I_SIMPLE_SELECTOR simpleSelectorFraction+)
+ ;
+
+simpleSelectorFraction
+ : elementSelector
+ | conditionSelector
+ ;
+
+conditionSelector
+@init
+{
+ ConditionType type = null;
+ String name = null;
+}
+@after
+{
+ $simpleSelector::conditions.add(
+ new CSSSelectorCondition(name, type, $start, tokenStream));
+}
+ : ^(DOT c=ID) { type = ConditionType.CLASS; name = $c.text; }
+ | HASH_WORD { type = ConditionType.ID; name = $HASH_WORD.text.substring(1); }
+ | ^(COLON s=ID) { type = ConditionType.PSEUDO; name = $s.text; }
+ ;
+
+elementSelector
+ : ^(PIPE ns=ID e1=ID)
+ { $simpleSelector::element = $e1.text;
+ $simpleSelector::namespace = $ns.text; }
+ | e2=ID
+ { $simpleSelector::element = $e2.text; }
+ | STAR
+ { $simpleSelector::element = $STAR.text; }
+ ;
+
+declarationsBlock returns [List<CSSProperty> properties]
+@init
+{
+ $properties = new ArrayList<CSSProperty>();
+}
+ : ^(I_DECL (declaration
+ {
+ if ($declaration.property != null)
+ $properties.add($declaration.property);
+ }
+ )*)
+ ;
+
+declaration returns [CSSProperty property]
+@after
+{
+ if ($id.text != null && $v.propertyValue != null)
+ $property = new CSSProperty($id.text, $v.propertyValue, $start, tokenStream);
+}
+ : ^(COLON id=ID v=value)
+ ;
+
+value returns [CSSPropertyValue propertyValue]
+ : ^( I_ARRAY
+ { final List<CSSPropertyValue> array = new ArrayList<CSSPropertyValue>(); }
+ ( s1=singleValue { array.add($s1.propertyValue); } )+
+ ) { $propertyValue = new CSSArrayPropertyValue(array, $start, tokenStream); }
+ | s2=singleValue { $propertyValue = $s2.propertyValue; }
+ ;
+
+singleValue returns [CSSPropertyValue propertyValue]
+ : NUMBER_WITH_UNIT
+ { $propertyValue = new CSSNumberPropertyValue($NUMBER_WITH_UNIT.text, $start, tokenStream); }
+ | HASH_WORD
+ { $propertyValue = new CSSColorPropertyValue($start, tokenStream); }
+ | RGB
+ { $propertyValue = new CSSRgbColorPropertyValue($RGB.text, $start, tokenStream); }
+ | ^(CLASS_REFERENCE cr=ARGUMENTS)
+ { $propertyValue = new CSSFunctionCallPropertyValue($CLASS_REFERENCE.text, $cr.text, $start, tokenStream); }
+ | ^(PROPERTY_REFERENCE pr=ARGUMENTS)
+ { $propertyValue = new CSSFunctionCallPropertyValue($PROPERTY_REFERENCE.text, $pr.text, $start, tokenStream); }
+ | ^(EMBED es=ARGUMENTS)
+ { $propertyValue = new CSSFunctionCallPropertyValue($EMBED.text, $es.text, $start, tokenStream); }
+ | ^(URL url=ARGUMENTS)
+ { $propertyValue = new CSSFunctionCallPropertyValue($URL.text, $url.text, $start, tokenStream); }
+ | ^(LOCAL l=ARGUMENTS)
+ { $propertyValue = new CSSFunctionCallPropertyValue($LOCAL.text, $l.text, $start, tokenStream); }
+ | s=STRING
+ { $propertyValue = new CSSStringPropertyValue($s.text, $start, tokenStream); }
+ | ID
+ { $propertyValue = CSSKeywordPropertyValue.create($start, tokenStream); }
+ ;
+
+argumentList returns [List<String> labels, List<String> values]
+@init
+{
+ $labels = new ArrayList<String>(3);
+ $values = new ArrayList<String>(3);
+}
+ : argument[$labels, $values]+
+ ;
+
+argument [List<String> labels, List<String> values]
+@after
+{
+ // Use null for argument without label.
+ $labels.add($l.text);
+ $values.add($v.text);
+}
+ : ^(EQUALS l=ID? v=STRING)
+ ;
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/antlr4/org/apache/flex/compiler/internal/css/CSS.g4
----------------------------------------------------------------------
diff --git a/compiler/src/main/antlr4/org/apache/flex/compiler/internal/css/CSS.g4 b/compiler/src/main/antlr4/org/apache/flex/compiler/internal/css/CSS.g4
new file mode 100644
index 0000000..61f42a9
--- /dev/null
+++ b/compiler/src/main/antlr4/org/apache/flex/compiler/internal/css/CSS.g4
@@ -0,0 +1,514 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ * This is a grammar for advanced CSS in Flex. It parses the CSS document and
+ * generate DOM objects.
+ */
+grammar CSS;
+
+options
+{
+ language = Java;
+// output = AST;
+// k = 2;
+}
+
+tokens
+{
+ I_RULES, I_MEDIUM_CONDITIONS, I_DECL, I_RULE, I_SELECTOR_GROUP, I_SELECTOR,
+ I_SIMPLE_SELECTOR, I_ARRAY
+}
+
+@header
+{
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
+import java.util.ArrayList;
+
+import org.apache.flex.compiler.problems.CSSParserProblem;
+}
+
+/*@lexer::header
+{
+package org.apache.flex.compiler.internal.css;
+
+import org.apache.flex.compiler.problems.CSSParserProblem;
+}
+
+@lexer::members
+{
+
+ * Lexer problems.
+protected List<CSSParserProblem> problems = new ArrayList<CSSParserProblem>();
+
+ * Collect lexer problems.
+@Override
+public void displayRecognitionError(String[] tokenNames, RecognitionException e)
+{
+ problems.add(CSSParserProblem.create(this, tokenNames, e));
+}
+}*/
+
+@members
+{
+
+/**
+ * Parser problems.
+ */
+/*protected List<CSSParserProblem> problems = new ArrayList<CSSParserProblem>();*/
+
+/**
+ * Collect parser problems.
+ */
+/*@Override
+public void displayRecognitionError(String[] tokenNames, RecognitionException e)
+{
+ problems.add(CSSParserProblem.create(this, tokenNames, e));
+}*/
+
+/**
+ * Check if the cursor is at the end of a simple selector.
+ */
+/*private final boolean endOfSimpleSelector()
+{
+ final CommonToken nextToken = (CommonToken) getTokenStream().LT(1);
+ if (nextToken == null)
+ return true;
+
+ // Check if there's white space between the previous token and the next token.
+ final CommonToken lastToken = (CommonToken) getTokenStream().LT(-1);
+ if (lastToken != null && nextToken != null)
+ {
+ final int lastStop = lastToken.getStopIndex();
+ final int nextStart = nextToken.getStartIndex();
+ if (lastStop + 1 < nextStart)
+ {
+ return true;
+ }
+ }
+
+ // If the next token is "{" or ",", it's also end of a selector.
+ final int nextType = nextToken.getType();
+ if (nextType == BLOCK_OPEN || nextType == COMMA)
+ {
+ return true;
+ }
+
+ return false;
+}*/
+
+}
+
+/**
+ * Root rule for a CSS file.
+ */
+stylesheet
+ : ( namespaceStatement | fontFace | mediaQuery | ruleset )*
+ ;
+
+/**
+ * This rule matches an "@namespace" statement.
+ *
+ * For example, declaring a namespace prefix:
+ * @namespace mx "library://ns.adobe.com/flex/mx";
+ *
+ * Declaring the default namespace:
+ * @namespace "library://ns.adobe.com/flex/spark";
+ */
+namespaceStatement
+ : AT_NAMESPACE ID? STRING SEMI_COLONS
+// -> ^(AT_NAMESPACE ID? STRING)
+ ;
+
+/**
+ * This rule matches a media query block.
+ *
+ * For example:
+ * @media all { ... }
+ *
+ * A media query block can have one or many rulesets inside.
+ */
+mediaQuery
+ : AT_MEDIA medium BLOCK_OPEN ruleset* BLOCK_END
+// -> ^(AT_MEDIA medium ruleset*)
+ ;
+
+/**
+ * This rule matches the actual Flex media query conditions.
+ * For example: (application-dpi: 240) and (os-platform: "Android")
+ */
+medium
+ : mediumCondition
+ (
+ // Flex only support "and" at the momement. (Shaoting)
+ 'and'
+ mediumCondition
+ )*
+// -> ^(I_MEDIUM_CONDITIONS mediumCondition*)
+ ;
+
+/**
+ * This rule matches a media query condition expression. It is either a
+ * word (like "all", "screen") or an expression like "(....)".
+ */
+mediumCondition
+ : ID
+ | ARGUMENTS
+ ;
+
+/**
+ * For example:
+ *
+ * @font-face {
+ * src: url("../assets/MyriadWebPro.ttf");
+ * fontFamily: myFontFamily;
+ * advancedAntiAliasing: true;
+ * }
+ *
+ * @see http://livedocs.adobe.com/flex/3/html/help.html?content=fonts_04.html
+ */
+fontFace
+ : AT_FONT_FACE declarationsBlock
+// -> ^(AT_FONT_FACE declarationsBlock)
+ ;
+
+/**
+ * This rule matches a CSS Ruleset.
+ */
+ruleset
+ : selectorGroup declarationsBlock
+// -> ^(I_RULE selectorGroup declarationsBlock)
+ ;
+
+/**
+ * This rule matches a group of comma-separated selectors.
+ */
+selectorGroup
+ : compoundSelector ( COMMA compoundSelector )*
+// -> ^(I_SELECTOR_GROUP compoundSelector+)
+ ;
+
+/**
+ * Compound selector is a chain of simple selectors connected by combinators.
+ * Each compound selector has one "subject", which is the element name of the
+ * right most simple selector in the chain.
+ *
+ * Currently, only descendant combinator (space) is supported.
+ * If we need to support combinators, add the terminals in this production.
+ *
+ * For example:
+ * s|VBox s|HBox.content s|Button
+ */
+compoundSelector
+@init
+{
+ final List<Object> simpleSelectorNodeList = new ArrayList<Object>();
+ //Object currentSimpleSelectorNode = adaptor.create(I_SIMPLE_SELECTOR, "I_SIMPLE_SELECTOR");
+ Token simpleSelectorStartToken = null;
+ Token simpleSelectorStopToken = null;
+}
+/*@after
+{
+ for(final Object simpleSelectorNode : simpleSelectorNodeList)
+ adaptor.addChild($compoundSelector.tree, simpleSelectorNode);
+}*/
+ : ( l=simpleSelectorFraction
+/* {
+ // expand token range of the current simple selector
+ if (simpleSelectorStartToken == null)
+ simpleSelectorStartToken = $l.start;
+ simpleSelectorStopToken = $l.stop;
+
+ adaptor.addChild(currentSimpleSelectorNode, $l.tree);
+
+ if (endOfSimpleSelector())
+ {
+ adaptor.setTokenBoundaries(
+ currentSimpleSelectorNode,
+ simpleSelectorStartToken,
+ simpleSelectorStopToken);
+ simpleSelectorNodeList.add(currentSimpleSelectorNode);
+
+ simpleSelectorStartToken = null;
+ simpleSelectorStopToken = null;
+
+ currentSimpleSelectorNode = adaptor.create(I_SIMPLE_SELECTOR, "I_SIMPLE_SELECTOR");
+ }
+ }*/
+ )+
+// -> ^(I_SELECTOR)
+ // Tree nodes for simple selectors are added in the @after block.
+ ;
+
+/**
+ * A compound selector consists of one or many simple selectors.
+ * This rule matches a fraction of a simple selector.
+ *
+ * s|HBox s|Button.confirm #activeLabel, <-- compound selector
+ * s|HBox <-- simple selector
+ * s|Button.confirm <-- simple selector
+ * #activeLabel <-- simple selector
+ *
+ * This rule will match each of the following 4 fractions:
+ *
+ * [s|HBox] [s|Button] [.confirm] [#activeLabel]
+ *
+ * As you can see, the parse tree isn't aware of the start and end of a simple
+ * selector. This is because white spaces have been ignored so that the parser
+ * can't distinguish between the following input:
+ *
+ * s|Button.rounded .labelText <-- 2 simple selectors
+ * s|Button.rounded.labelText <-- 1 simple selector
+ *
+ * As a result, this rule could match only part of a simple selector, because
+ * the conditions were broken into multiple tokens.
+ */
+simpleSelectorFraction
+ : element
+ | condition
+ ;
+
+/**
+ * This rule matches a condition selector.
+ * For example: ".styleName", "#loginButton", ":up"
+ */
+condition
+ : ( DOT ID
+ | HASH_WORD
+ | COLON ID
+ )
+ ;
+
+/**
+ * This rule matches an element name with or without namespace prefix. It also
+ * matches the special "any" element "*".
+ * For example: "s|Panel", "Label", "*"
+ */
+element
+ : ID PIPE ID
+ | ID
+ | STAR
+ ;
+
+/**
+ * This rule matches a declarations block.
+ * For example:
+ * { font-size:12; font-family: "sans"; }
+ */
+declarationsBlock
+ : BLOCK_OPEN
+ (
+ SEMI_COLONS? // multiple semi-colons are legal
+ declaration
+ (
+ SEMI_COLONS
+ declaration
+ )*
+ SEMI_COLONS?
+ )?
+ BLOCK_END
+// -> ^(I_DECL declaration*)
+ ;
+
+/**
+ * This rule matches property declaration. The declaration is a key value pair.
+ * For example:
+ * font-size:12px
+ */
+declaration
+ : ID COLON value
+// -> ^(COLON ID value)
+ ;
+
+/**
+ * This rule matches an array of property values or a single value.
+ * If it matches an array, the output is an I_ARRAY tree of element values.
+ * If it matches an single value, the output is a "singleValue" tree.
+ *
+ * Array example:
+ * 2.0, 2.0, 3.0, 3.0
+ * "tl", "tr", "bl", "br"
+ * #FFFFFF, #FFFFFF, #FFFFFF, #FFFFFF
+ * Verdana, Times, Sans-Serif
+ * solid 1px #666666
+ *
+ */
+value
+@init { int count = 1; }
+ : singleValue ( COMMA? singleValue { count++; } )*
+// -> {count > 1}? ^(I_ARRAY singleValue+)
+// -> singleValue
+ ;
+
+/**
+ * This rule matches one property value.
+ *
+ * For example:
+ * 12, 12px, 100%.
+ * #FF3322
+ * rgb(100%, 100%, 100%)
+ * ClassReference("mx.controls.Button")
+ * PropertyReference("size")
+ * Embed(source="assets/logo.png", mimeType="images/png")
+ * url("../fonts/myfont.ttf")
+ * local("My Font")
+ * "Times New Roman"
+ * italic
+ */
+singleValue
+ : NUMBER_WITH_UNIT
+ | HASH_WORD
+ | CLASS_REFERENCE ARGUMENTS
+// -> ^(CLASS_REFERENCE ARGUMENTS)
+ | PROPERTY_REFERENCE ARGUMENTS
+// -> ^(PROPERTY_REFERENCE ARGUMENTS)
+ | EMBED ARGUMENTS
+// -> ^(EMBED ARGUMENTS)
+ | URL ARGUMENTS
+// -> ^(URL ARGUMENTS)
+ | LOCAL ARGUMENTS
+// -> ^(LOCAL ARGUMENTS)
+ | RGB
+ | STRING
+ | ID
+ ;
+
+/* Lexer Rules */
+
+BLOCK_OPEN : '{' ;
+BLOCK_END : '}' ;
+COMMA : ',' ;
+PERCENT : '%' ;
+PIPE : '|' ;
+STAR : '*' ;
+DOT : '.' ;
+EQUALS: '=';
+AT_NAMESPACE : '@namespace' ;
+AT_MEDIA : '@media' ;
+COLON : ':' ;
+AT_FONT_FACE : '@font-face' ;
+CLASS_REFERENCE : 'ClassReference' ;
+PROPERTY_REFERENCE : 'PropertyReference' ;
+EMBED : 'Embed' ;
+URL : 'url' ;
+LOCAL : 'local' ;
+NULL : 'null' ;
+
+/**
+ * Matches a rgb definition - rgb(100%,100%,100%)
+ */
+RGB : 'rgb(' ( WS* NUMBER ( PERCENT | ) WS* ) ','
+ ( WS* NUMBER ( PERCENT | ) WS* ) ','
+ ( WS* NUMBER ( PERCENT | ) WS* )
+ ')' ;
+
+/** Arguments of a function call property value. */
+ARGUMENTS
+ : '(' .*? ')'
+ ;
+/**
+ * Match multiple semi-colons in Lexer level so that the parser can have a
+ * finite number of look ahead, instead of LL(*);
+ */
+SEMI_COLONS : ';'+ ;
+
+/**
+ * Matches either ID selector or color value. Unfortunately, these two types of
+ * tokens are ambiguous in ANTLR world.
+ */
+HASH_WORD
+ : '#' ( LETTER | DIGIT | '-' | '_' )+
+ ;
+
+ID : ( '-' | '_' )? LETTER ( LETTER | DIGIT | '-' | '_' )*
+ ;
+
+fragment
+LETTER
+ : 'a'..'z'
+ | 'A'..'Z'
+ ;
+
+/**
+ * Matches: 100, -100, +3.14, .25, -0.25, +.25
+ */
+fragment
+NUMBER
+ : ('+'|'-')?
+ ( DIGIT+ (DOT DIGIT+)?
+ | DOT DIGIT+
+ )
+ ;
+
+/**
+ * Matches a number with optinal unit string.
+ * For example:
+ * 2.5
+ * 2.5em
+ * 100%
+ *
+ * The grammar doesn't allow spaces between the number and the unit.
+ * For example: 35 em is a "NUMBER" and an "ID".
+ * Otherwise such input will be ambigiuous:
+ * font-style: bold 35 pt 25em
+ * "pt" could either be another keyword or the unit of "35".
+ */
+NUMBER_WITH_UNIT
+ : NUMBER (ID|PERCENT)?
+ ;
+
+fragment
+DIGIT
+ : '0'..'9'
+ ;
+
+COMMENT
+ : '/*' .*? '*/'
+ ;
+
+WS : ( ' ' | '\t' | '\r' | '\n' )
+ ;
+
+STRING
+ : ['"''\']
+ ( ~( '\\' | ['"''\'] ) )*
+ ['"''\']
+ ;
+