Beispiel #1
0
  /**
   * With start token being the first non-ignorable token inside the declaration block, iterate
   * issuing CssDeclaration objects until the block ends.
   */
  private void handleDeclarationBlock(
      CssToken start, CssTokenIterator iter, final CssContentHandler doc, CssErrorHandler err)
      throws CssException {

    while (true) {
      if (MATCH_CLOSEBRACE.apply(start)) {
        return;
      }
      CssDeclaration decl = handleDeclaration(start, iter, doc, err, false);
      try {
        if (decl != null) {
          doc.declaration(decl);
          if (debug) {
            checkState(MATCH_SEMI_CLOSEBRACE.apply(iter.last));
          }

          // continue or return: we may be at "; next decl" or "}" or ";}"
          if (MATCH_CLOSEBRACE.apply(iter.last)) {
            return;
          } else if (MATCH_SEMI.apply(iter.last) && MATCH_CLOSEBRACE.apply(iter.peek())) {
            iter.next();
            return;
          } else {
            if (debug) {
              checkState(MATCH_SEMI.apply(iter.last));
            }
            // we have ';', expect another decl
            start = iter.next(); // first token after ';'
          }

        } else {
          // #handleDeclaration returned null to signal error
          // #handleDeclaration has issued errors, we forward
          start = iter.next(MATCH_SEMI_CLOSEBRACE);
          if (MATCH_SEMI.apply(start)) {
            start = iter.next();
          }
        }
      } catch (NoSuchElementException nse) {
        err.error(
            new CssGrammarException(
                GRAMMAR_PREMATURE_EOF, iter.last.location, "';' " + Messages.get("or") + " '}'"));
        throw new PrematureEOFException();
      }
    }
  }
Beispiel #2
0
 /**
  * With iter.last at '{', discover the at-rule type. The contents is a ruleset if '{' comes before
  * ';' or '}'.
  */
 private boolean hasRuleSet(CssAtRule atRule, CssTokenIterator iter) {
   int debugIndex;
   if (debug) {
     checkArgument(iter.last.getChar() == '{');
     debugIndex = iter.index();
   }
   List<CssToken> list = iter.list;
   for (int i = iter.index() + 1; i < list.size(); i++) {
     CssToken tk = list.get(i);
     if (MATCH_OPENBRACE.apply(tk)) {
       return true;
     } else if (MATCH_SEMI_CLOSEBRACE.apply(tk)) {
       return false;
     }
   }
   if (debug) {
     checkState(iter.last.getChar() == '{');
     checkState(iter.index() == debugIndex);
   }
   return false;
 }
Beispiel #3
0
  /** Parse a CSS document. */
  public void parse(
      final Reader reader,
      final String systemID,
      final CssErrorHandler err,
      final CssContentHandler doc)
      throws IOException, CssException {

    CssTokenIterator iter = scan(reader, systemID, err);

    doc.startDocument();

    while (iter.hasNext(FILTER_S_CMNT_CDO_CDC)) {
      CssToken tk = iter.next(FILTER_S_CMNT_CDO_CDC);
      try {

        if (tk.type == CssToken.Type.ATKEYWORD) {
          handleAtRule(tk, iter, doc, err);
          if (debug) {
            checkArgument(MATCH_SEMI_CLOSEBRACE.apply(iter.last));
          }
        } else {
          handleRuleSet(tk, iter, doc, err);
          if (debug) {
            checkArgument(MATCH_CLOSEBRACE.apply(iter.last));
          }
        }

      } catch (PrematureEOFException te) {
        // The subroutines report premature EOF to ErrHandler
        // on occurrence; if the listener rethrows it will
        // be a CssException so we don't catch it here.
        break;
      }
    }

    doc.endDocument();
  }
Beispiel #4
0
  /**
   * With start expected to be an IDENT token representing the property name, build the declaration
   * and return after hitting ';' or '}'. On error, issue to errhandler, return null, caller
   * forwards.
   */
  private CssDeclaration handleDeclaration(
      CssToken name,
      CssTokenIterator iter,
      CssContentHandler doc,
      CssErrorHandler err,
      boolean isStyleAttribute)
      throws CssException {

    if (name.type != CssToken.Type.IDENT) {
      err.error(
          new CssGrammarException(
              GRAMMAR_EXPECTING_TOKEN,
              name.location,
              name.getChars(),
              Messages.get("a_property_name")));
      return null;
    }

    CssDeclaration declaration = new CssDeclaration(name.getChars(), name.location);

    try {
      if (!MATCH_COLON.apply(iter.next())) {
        err.error(
            new CssGrammarException(
                GRAMMAR_EXPECTING_TOKEN, name.location, iter.last.getChars(), ":"));
        return null;
      }
    } catch (NoSuchElementException nse) {
      err.error(new CssGrammarException(GRAMMAR_PREMATURE_EOF, iter.last.location, ":"));
      throw new PrematureEOFException();
    }

    try {
      while (true) {
        CssToken value = iter.next();
        if (MATCH_SEMI_CLOSEBRACE.apply(value)) {
          if (declaration.components.size() < 1) {
            err.error(
                new CssGrammarException(
                    GRAMMAR_EXPECTING_TOKEN,
                    iter.last.location,
                    value.getChar(),
                    Messages.get("a_property_value")));
            return null;
          } else {
            return declaration;
          }
        } else {
          if (!handlePropertyValue(declaration, value, iter, isStyleAttribute)) {
            err.error(
                new CssGrammarException(
                    GRAMMAR_UNEXPECTED_TOKEN, iter.last.location, iter.last.getChars()));
            return null;
          } else {
            if (isStyleAttribute && !iter.hasNext()) {
              return declaration;
            }
          }
        }
      }
    } catch (NoSuchElementException nse) {
      err.error(
          new CssGrammarException(
              GRAMMAR_PREMATURE_EOF, iter.last.location, "';' " + Messages.get("or") + " '}'"));
      throw new PrematureEOFException();
    }
  }