changeset 7837:b72f6918383b

RT-38455: [CSS] lexer should not consume @font-face and @import as one token
author David Grieve<david.grieve@oracle.com>
date Thu, 28 Aug 2014 19:54:23 -0400
parents 62aa644a60d4
children aa3fda00ace5
files modules/graphics/src/main/java/com/sun/javafx/css/parser/CSSLexer.java modules/graphics/src/main/java/com/sun/javafx/css/parser/CSSParser.java
diffstat 2 files changed, 79 insertions(+), 72 deletions(-) [+]
line wrap: on
line diff
--- a/modules/graphics/src/main/java/com/sun/javafx/css/parser/CSSLexer.java	Thu Aug 28 16:46:20 2014 +0300
+++ b/modules/graphics/src/main/java/com/sun/javafx/css/parser/CSSLexer.java	Thu Aug 28 19:54:23 2014 -0400
@@ -79,6 +79,7 @@
     final static int IMPORT = 44;
     final static int SECONDS = 45;
     final static int MS = 46;
+    final static int AT_KEYWORD = 47;
 
     private final Recognizer A = (c) -> c == 'a' || c == 'A';
     private final Recognizer B = (c) -> c == 'b' || c == 'B';
@@ -966,31 +967,8 @@
                         return tok;
 
                     case '@':
-                        // read word after '@' symbol
-                        StringBuilder keywordSB = new StringBuilder();
-                        do {
-                            ch = readChar();
-                            keywordSB.append((char)ch);
-                        } while (!WS_CHARS.recognize(ch) && ch != Token.EOF);
-                        String keyword = keywordSB.substring(0,keywordSB.length()-1);
-                        if ("font-face".equalsIgnoreCase(keyword)) {
-                            token = new Token(FONT_FACE,"@font-face", line, offset);
-                            offset = pos;
-                        } else if ("import".equalsIgnoreCase(keyword)) {
-                            token = new Token(IMPORT,"@import", line, offset);
-                            offset = pos;
-                        } else {
-                            // Skip over other at-rules
-                            do {
-                                ch = readChar();
-                            } while (ch != ';' &&
-                                     ch != Token.EOF);
-                            if (ch == ';') {
-                                ch = readChar();
-                                token = Token.SKIP_TOKEN;
-                                offset = pos;
-                            }
-                        }
+                        token = new Token(AT_KEYWORD, "@", line, offset);
+                        offset = pos;
                         break;
 
                     default:
--- a/modules/graphics/src/main/java/com/sun/javafx/css/parser/CSSParser.java	Thu Aug 28 16:46:20 2014 +0300
+++ b/modules/graphics/src/main/java/com/sun/javafx/css/parser/CSSParser.java	Thu Aug 28 19:54:23 2014 -0400
@@ -3866,53 +3866,21 @@
         // need to read the first token
         currentToken = nextToken(lexer);
 
-        while ((currentToken != null) &&
-               (currentToken.getType() != Token.EOF)) {
-
-            if (currentToken.getType() == CSSLexer.FONT_FACE) {
-                FontFace fontFace = fontFace(lexer);
-                if (fontFace != null) stylesheet.getFontFaces().add(fontFace);
-                currentToken = nextToken(lexer);
-                continue;
-
-            } else if (currentToken.getType() == CSSLexer.IMPORT) {
-
-                if (CSSParser.imports == null) {
-                    CSSParser.imports = new Stack<>();
+        while((currentToken != null) &&
+                (currentToken.getType() == CSSLexer.AT_KEYWORD)) {
+
+            currentToken = nextToken(lexer);
+
+            if (currentToken == null || currentToken.getType() != CSSLexer.IDENT) {
+
+                // just using ParseException for a nice error message, not for throwing the exception.
+                ParseException parseException = new ParseException("Expected IDENT", currentToken, this);
+                final String msg = parseException.toString();
+                CssError error = createError(msg);
+                if (LOGGER.isLoggable(Level.WARNING)) {
+                    LOGGER.warning(error.toString());
                 }
-
-                if (!imports.contains(sourceOfStylesheet)) {
-
-                    imports.push(sourceOfStylesheet);
-
-                    Stylesheet importedStylesheet = handleImport(lexer);
-
-                    if (importedStylesheet != null) {
-                        List<Rule> importedRules = importedStylesheet.getRules();
-                        if (importedRules != null && !importedRules.isEmpty()) {
-                            stylesheet.getRules().addAll(importedRules);
-                        }
-                    }
-
-                    imports.pop();
-
-                    if (CSSParser.imports.isEmpty()) {
-                        CSSParser.imports = null;
-                    }
-
-                } else {
-                    // Import imports import!
-                    final int line = currentToken.getLine();
-                    final int pos = currentToken.getOffset();
-                    final String msg =
-                            MessageFormat.format("Recursive @import at {2} [{0,number,#},{1,number,#}]",
-                                    line,pos,imports.peek());
-                    CssError error = createError(msg);
-                    if (LOGGER.isLoggable(Level.WARNING)) {
-                        LOGGER.warning(error.toString());
-                    }
-                    reportError(error);
-                }
+                reportError(error);
 
                 // get past EOL or SEMI
                 do {
@@ -3921,10 +3889,71 @@
                         (currentToken.getType() == CSSLexer.SEMI) ||
                         (currentToken.getType() == CSSLexer.WS) ||
                         (currentToken.getType() == CSSLexer.NL));
-
                 continue;
             }
 
+            String keyword = currentToken.getText().toLowerCase(Locale.ROOT);
+            if ("font-face".equals(keyword)) {
+                FontFace fontFace = fontFace(lexer);
+                if (fontFace != null) stylesheet.getFontFaces().add(fontFace);
+                currentToken = nextToken(lexer);
+                continue;
+
+            } else if ("import".equals(keyword)) {
+
+                if (CSSParser.imports == null) {
+                    CSSParser.imports = new Stack<>();
+                }
+
+                if (!imports.contains(sourceOfStylesheet)) {
+
+                    imports.push(sourceOfStylesheet);
+
+                    Stylesheet importedStylesheet = handleImport(lexer);
+
+                    if (importedStylesheet != null) {
+                        List<Rule> importedRules = importedStylesheet.getRules();
+                        if (importedRules != null && !importedRules.isEmpty()) {
+                            stylesheet.getRules().addAll(importedRules);
+                        }
+                    }
+
+                    imports.pop();
+
+                    if (CSSParser.imports.isEmpty()) {
+                        CSSParser.imports = null;
+                    }
+
+                } else {
+// Import imports import!
+                    final int line = currentToken.getLine();
+                    final int pos = currentToken.getOffset();
+                    final String msg =
+                            MessageFormat.format("Recursive @import at {2} [{0,number,#},{1,number,#}]",
+                                    line, pos, imports.peek());
+                    CssError error = createError(msg);
+                    if (LOGGER.isLoggable(Level.WARNING)) {
+                        LOGGER.warning(error.toString());
+                    }
+                    reportError(error);
+                }
+
+                // get past EOL or SEMI
+                do {
+                    currentToken = lexer.nextToken();
+                } while ((currentToken != null) &&
+                        (currentToken.getType() == CSSLexer.SEMI) ||
+                        (currentToken.getType() == CSSLexer.WS) ||
+                        (currentToken.getType() == CSSLexer.NL));
+
+                continue;
+
+            }
+        }
+
+        while ((currentToken != null) &&
+               (currentToken.getType() != Token.EOF)) {
+
             List<Selector> selectors = selectors(lexer);
             if (selectors == null) return;