summaryrefslogtreecommitdiffstats
path: root/src/dom/cssparser.cpp
diff options
context:
space:
mode:
authorBob Jamison <ishmalius@gmail.com>2008-05-01 19:23:00 +0000
committerishmal <ishmal@users.sourceforge.net>2008-05-01 19:23:00 +0000
commitb225eaeb43213b248eb081702c45e9e7216d3003 (patch)
tree856528be9bda3a41e4a2206387ffc93fa3686084 /src/dom/cssparser.cpp
parentClean up. More commenting. Smarten SvgParser and rename to SvgReader. (diff)
downloadinkscape-b225eaeb43213b248eb081702c45e9e7216d3003.tar.gz
inkscape-b225eaeb43213b248eb081702c45e9e7216d3003.zip
Rename *Parsers to Readers
(bzr r5571)
Diffstat (limited to 'src/dom/cssparser.cpp')
-rw-r--r--src/dom/cssparser.cpp1670
1 files changed, 0 insertions, 1670 deletions
diff --git a/src/dom/cssparser.cpp b/src/dom/cssparser.cpp
deleted file mode 100644
index 422c02e49..000000000
--- a/src/dom/cssparser.cpp
+++ /dev/null
@@ -1,1670 +0,0 @@
-/**
- * Phoebe DOM Implementation.
- *
- * This is a C++ approximation of the W3C DOM model, which follows
- * fairly closely the specifications in the various .idl files, copies of
- * which are provided for reference. Most important is this one:
- *
- * http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/idl-definitions.html
- *
- * Authors:
- * Bob Jamison
- *
- * Copyright (C) 2005-2008 Bob Jamison
- *
- * This library 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 2.1 of the License, or (at your option) any later version.
- *
- * This library 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 library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "cssparser.h"
-#include "ucd.h"
-
-#include <stdio.h>
-#include <stdarg.h>
-
-namespace org
-{
-namespace w3c
-{
-namespace dom
-{
-namespace css
-{
-
-//#########################################################################
-//# M E S S A G E S
-//#########################################################################
-
-/**
- * Get the column and row number of the given character position
- */
-void CssParser::getColumnAndRow(int p, int &colResult, int &rowResult, int &lastNL)
-{
- int col = 1;
- int row = 1;
- int lastnl = 0;
-
- for (int i=0 ; i<p ; i++)
- {
- XMLCh ch = parsebuf[i];
- if (ch == '\n')
- {
- lastnl = i;
- row++;
- col=0;
- }
- else
- col++;
- }
-
- colResult = col;
- rowResult = row;
- lastNL = lastnl;
-}
-
-/**
- *
- */
-void CssParser::error(char const *fmt, ...)
-{
- int lineNr;
- int colNr;
- int lastNL;
- getColumnAndRow(lastPosition, colNr, lineNr, lastNL);
-
- va_list args;
- fprintf(stderr, "CssParser:error at %d, line %d, column %d:",
- lastPosition, lineNr, colNr);
- va_start(args, fmt);
- vfprintf(stderr, fmt, args);
- va_end(args) ;
- fprintf(stderr, "\n");
-
- /*
- int lineLen = lastPosition - lastNL;
- printf("lineLen:%d lastNL:%d\n", lineLen, lastNL);
- for (int i=lastNL+1 ; i<lastPosition ; i++)
- fprintf(stderr, "%c", parsebuf[i]);
- fprintf(stderr, "\n");
- for (int i=0 ; i<lineLen-1 ; i++)
- fprintf(stderr, " ");
- fprintf(stderr, "^\n");
- */
- for (int i=0 ; i<lastPosition ; i++)
- fprintf(stderr, "%c", parsebuf[i]);
- fprintf(stderr, "\n");
-}
-
-
-
-//#########################################################################
-//# P A R S I N G
-//#########################################################################
-
-/**
- * Get the character at the position and record the fact
- */
-XMLCh CssParser::get(int p)
-{
- if (p >= parselen)
- return 0;
- XMLCh ch = parsebuf[p];
- //printf("%c", ch);
- lastPosition = p;
- return ch;
-}
-
-
-
-/**
- * Test if the given substring exists at the given position
- * in parsebuf. Use get() in case of out-of-bounds
- */
-bool CssParser::match(int pos, const char *str)
-{
- while (*str)
- {
- if (get(pos++) != (XMLCh) *str++)
- return false;
- }
- return true;
-}
-
-/**
- *
- */
-int CssParser::skipwhite(int p)
-{
- while (p < parselen)
- {
- //# XML COMMENT
- if (match(p, "<!--"))
- {
- p+=4;
- bool done=false;
- while (p<parselen)
- {
- if (match(p, "-->"))
- {
- p+=3;
- done=true;
- break;
- }
- p++;
- }
- lastPosition = p;
- if (!done)
- {
- error("unterminated <!-- .. --> comment");
- return -1;
- }
- }
- //# C comment
- else if (match(p, "/*"))
- {
- p+=2;
- bool done=false;
- while (p<parselen)
- {
- if (match(p, "*/"))
- {
- p+=2;
- done=true;
- break;
- }
- p++;
- }
- lastPosition = p;
- if (!done)
- {
- error("unterminated /* .. */ comment");
- return -1;
- }
- }
- else if (!uni_is_space(get(p)))
- break;
- else
- p++;
- }
- lastPosition = p;
- return p;
-}
-
-/**
- * get a word from the buffer
- */
-int CssParser::getWord(int p, DOMString &result)
-{
- XMLCh ch = get(p);
- if (!uni_is_letter(ch))
- return p;
- DOMString str;
- str.push_back(ch);
- p++;
-
- while (p < parselen)
- {
- ch = get(p);
- if (uni_is_letter_or_digit(ch) || ch=='-' || ch=='_')
- {
- str.push_back(ch);
- p++;
- }
- else if (ch == '\\')
- {
- p+=2;
- }
- else
- break;
- }
- result = str;
- return p;
-}
-
-
-/**
- * get a word from the buffer
- */
-int CssParser::getNumber(int p0, double &result)
-{
- int p=p0;
- DOMString str;
- while (p < parselen)
- {
- XMLCh ch = get(p);
- if (ch<'0' || ch>'9')
- break;
- str.push_back(ch);
- p++;
- }
- if (get(p) == '.' && get(p+1)>='0' && get(p+1)<='9')
- {
- p++;
- str.push_back('.');
- while (p < parselen)
- {
- XMLCh ch = get(p);
- if (ch<'0' || ch>'9')
- break;
- str.push_back(ch);
- p++;
- }
- }
- if (p>p0)
- {
- char *start = (char *)str.c_str();
- char *end = NULL;
- double val = strtod(start, &end);
- if (end > start)
- {
- result = val;
- return p;
- }
- }
-
- //not a number
- return p0;
-}
-
-
-
-/**
- * Assume that we are starting on a quote. Ends on the char
- * after the final '"'
- */
-int CssParser::getQuoted(int p0, DOMString &result)
-{
-
- int p = p0;
-
- XMLCh quoteChar = get(p);
- if (quoteChar != '"' && quoteChar != '\'')
- return p0;
-
- p++;
-
- DOMString buf;
-
- bool done = false;
- while (p<parselen )
- {
- XMLCh ch = get(p);
- if (ch == quoteChar)
- {
- done = true;
- p++;
- break;
- }
- else
- {
- buf.push_back(ch);
- }
- p++;
- }
-
- if (!done)
- {
- error("unterminated quoted string");
- return -1;
- }
-
- result.append(buf);
-
- return p;
-}
-
-/**
- * Not in api. replaces URI return by lexer
- */
-int CssParser::getUri(int p0, DOMString &str)
-{
- int p = p0;
- if (!match(p, "url("))
- return p0;
- p+=4;
- p = skipwhite(p);
- DOMString buf;
- XMLCh ch;
- while (p < parselen)
- {
- ch = get(p);
- if (isspace(ch) || ch==')')
- break;
- buf.push_back(ch);
- p++;
- }
- p = skipwhite(p);
- ch = get(p);
- if (ch != ')')
- {
- error("no closing ')' on url spec");
- return -1;
- }
- p++;
- str = buf;
- return p;
-}
-
-/**
- * Skip to the end of the block
- */
-int CssParser::skipBlock(int p0)
-{
- int p = p0;
- while (p < parselen)
- {
- XMLCh ch = get(p);
- if (ch == '}')
- {
- p++;
- break;
- }
- else
- {
- p++;
- }
- }
- return p;
-}
-
-//#########################################################################
-//# P R O D U C T I O N S
-//#########################################################################
-
-/**
- * stylesheet
- * : [ CHARSET_SYM S* STRING S* ';' ]?
- * [S|CDO|CDC]* [ import [S|CDO|CDC]* ]*
- * [ [ ruleset | media | page ] [S|CDO|CDC]* ]*
- * ;
- */
-int CssParser::getStyleSheet(int p0)
-{
- int p = p0;
- int p2 = p;
- XMLCh ch;
-
- //# CHARSET 0 or 1
- if (match(p, "@charset"))
- {
- p+=8;
- p = skipwhite(p);
- DOMString str;
- p2 = getQuoted(p, str);
- if (p2<=p)
- {
- error("quoted string required after @charset");
- return -1;
- }
- p = skipwhite(p2);
- ch = get(p);
- if (ch !=';')
- {
- error("';' required after @charset declaration");
- return -1;
- }
- p++;
- p = skipwhite(p);
- }
-
- //# IMPORT 0 to many
- while (true)
- {
- p2 = getImport(p);
- if (p2<0)
- {
- return -1;
- }
- if (p2<=p)
- break;
- p = p2;
- }
-
- //# RULESET | MEDIA | PAGE 0 to many
- while (true)
- {
- //Ruleset
- p2 = getRuleSet(p);
- if (p2<0)
- {
- return -1;
- }
- if (p2>p)
- {
- p = p2;
- continue;
- }
-
- //Media
- p2 = getMedia(p);
- if (p2<0)
- {
- return -1;
- }
- if (p2>p)
- {
- p = p2;
- continue;
- }
-
- //Page
- p2 = getPage(p);
- if (p2<0)
- {
- return -1;
- }
- if (p2>p)
- {
- p = p2;
- continue;
- }
-
- //none of the above
- break;
- }
-
- return p;
-}
-
-/**
- * import
- * : IMPORT_SYM S*
- * [STRING|URI] S* [ medium [ COMMA S* medium]* ]? ';' S*
- * ;
- */
-int CssParser::getImport(int p0)
-{
- int p = p0;
- if (!match(p, "@import"))
- return p0;
- p+=7;
- p = skipwhite(p);
-
- //# STRING | URI
- DOMString str;
- int p2 = getQuoted(p, str);
- if (p2<0)
- {
- return -1;
- }
- if (p2<=p)
- {
- p2 = getUri(p, str);
- if (p2<0)
- {
- return -1;
- }
- if (p2<=p)
- {
- error("quoted string or URI required after @import");
- return -1;
- }
- }
- p = p2;
- p2 = getMedium(p);
- if (p2<0)
- return -1;
-
- p = p2;
- p = skipwhite(p);
- XMLCh ch = get(p);
- if (ch != ';')
- {
- error("@import must be terminated with ';'");
- return -1;
- }
- p++;
- return p;
-}
-
-/**
- * media
- * : MEDIA_SYM S* medium [ COMMA S* medium ]* LBRACE S* ruleset* '}' S*
- * ;
- */
-int CssParser::getMedia(int p0)
-{
- int p = p0;
- XMLCh ch;
- if (!match(p, "@media"))
- return p0;
- p+=6;
- p = skipwhite(p);
-
- //# MEDIUM LIST
- int p2 = getMedium(p);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- error("@media must be followed by medium");
- return -1;
- }
- p = p2;
- while (true)
- {
- ch = get(p);
- if (ch != ',')
- break;
- p2 = getMedium(p);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- error("',' in medium list must be followed by medium");
- return -1;
- }
- p = p2;
- }
-
- p = skipwhite(p);
- ch = get(p);
- if (ch!='{')
- {
- error("@media requires '{' for ruleset");
- return -1;
- }
- p++;
- p2 = getRuleSet(p);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- error("@media requires ruleset after '{'");
- return -1;
- }
- p = p2;
- ch = get(p);
- if (ch != '}')
- {
- error("@media requires '}' after ruleset");
- return -1;
- }
- p++;
- return p0;
-}
-
-/**
- * medium
- * : IDENT S*
- * ;
- */
-int CssParser::getMedium(int p0)
-{
- int p = p0;
- p = skipwhite(p);
-
- DOMString ident;
- int p2 = getWord(p, ident);
- if (p2<0)
- return -1;
- if (p2<=p)
- return p0;
- p = p2;
-
- return p;
-}
-
-/**
- * page
- * : PAGE_SYM S* pseudo_page? S*
- * LBRACE S* declaration [ ';' S* declaration ]* '}' S*
- * ;
- */
-int CssParser::getPage(int p0)
-{
- int p = p0;
-
- //# @PAGE
- p = skipwhite(p);
- if (!match(p, "@page"))
- return p0;
- p+= 5;
-
- //#PSEUDO PAGE 0 or 1
- p = skipwhite(p);
- int p2 = getPseudoPage(p);
- if (p2<0)
- return -1;
- if (p2>p)
- {
- p = p2;
- }
-
- //# {
- p=skipwhite(p);
- XMLCh ch = get(p);
- if (p != '{')
- {
- error("@page requires '{' before declarations");
- }
- p++;
-
- //# DECLARATION LIST
- p = skipwhite(p);
- CSSStyleDeclaration declarationList;
- p2 = getDeclaration(p, declarationList);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- error("@page requires declaration(s) after '{'");
- return -1;
- }
- while (true)
- {
- p = skipwhite(p2);
- ch = get(p);
- if (ch != ';')
- break;
- p++;
- p = skipwhite(p);
- p2 = getDeclaration(p, declarationList);
- if (p2<0)
- return -1;
- if (p2<= p)
- {
- error("@page requires declaration after ';'");
- return -1;
- }
- }
-
- //# }
- p=skipwhite(p);
- ch = get(p);
- if (p != '}')
- {
- error("@page requires '}' after declarations");
- }
- p++;
-
- return p;
-}
-
-/**
- * pseudo_page
- * : ':' IDENT
- * ;
- */
-int CssParser::getPseudoPage(int p0)
-{
- int p = p0;
- if (!match(p, ":"))
- return p0;
- p++;
- DOMString str;
- int p2 = getWord(p, str);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- error("pseudo-page requires identifier after ':'");
- return -1;
- }
- p = p2;
- return p;
-}
-
-/**
- * ruleset
- * : selector [ COMMA S* selector ]*
- * LBRACE S* declaration [ ';' S* declaration ]* '}' S*
- * ;
- */
-int CssParser::getRuleSet(int p0)
-{
- int p = p0;
- XMLCh ch;
-
- //## SELECTOR
- p = skipwhite(p);
- int p2 = getSelector(p);
- if (p2<0)
- return -1;
- if (p2<=p) //no selector
- {
- if (get(p) != '{')//check for selector-less rule
- return p0;//not me
- }
- p = p2;
- while (true)
- {
- p = skipwhite(p);
- ch = get(p);
- if (ch != ',')
- break;
- p++;
- p = skipwhite(p);
- int p2 = getSelector(p);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- error("selector required after ',' in list");
- return -1;
- }
- p = p2;
- }
-
- //## {
- ch = get(p);
- if (ch != '{')
- {
- error("'{' required before declarations of ruleset");
- return -1;
- }
- p++;
-
- //## DECLARATIONS ( 0 to many )
- CSSStyleDeclaration declarationList;
-
- p = skipwhite(p);
- p2 = getDeclaration(p, declarationList);
- if (p2<0)
- return -1;
- if (p2>p)
- {
- p = p2;
- while (true)
- {
- p = skipwhite(p);
- ch = get(p);
- if (ch != ';')
- break;
- p++;
- p = skipwhite(p);
- p2 = getDeclaration(p, declarationList);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- //apparently this is ok
- //error("declaration required after ';' in ruleset");
- //return -1;
- break;
- }
- p = p2;
- }
- }
- //## }
- ch = get(p);
- if (ch != '}')
- {
- error("ruleset requires closing '}'");
- return -1;
- }
- p++;
- p = skipwhite(p);
-
- return p;
-}
-
-/**
- * selector
- * : simple_selector [ combinator simple_selector ]*
- * ;
- */
-int CssParser::getSelector(int p0)
-{
- int p = p0;
-
- //## SIMPLE SELECTOR
- p = skipwhite(p);
- int p2 = getSimpleSelector(p);
- if (p2<0)
- return -1;
- if (p2<=p)
- return p0; //not me
- p = p2;
-
- //## COMBINATORS + MORE SELECTORS
- while (true)
- {
- XMLCh ch = get(p);
- bool wasSpace = isspace(ch);
- p = skipwhite(p);
- ch = get(p);
- //# Combinators
- //easier to do here than have a getCombinator()
- int visibleCombinator = false;
- if (ch == '+')
- {
- visibleCombinator = true;
- p++;
- }
- else if (ch == '>')
- {
- visibleCombinator = true;
- p++;
- }
- else if (wasSpace)
- {
- }
- else
- {
- break;
- }
- p = skipwhite(p);
- p2 = getSimpleSelector(p);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- if (visibleCombinator)
- {
- error("need simple selector after combinator");
- return -1;
- }
- else
- {
- break;
- }
- }
- p = p2;
- }
- return p;
-}
-
-/**
- * simple_selector
- * : element_name [ HASH | class | attrib | pseudo ]*
- * | [ HASH | class | attrib | pseudo ]+
- * ;
- */
-int CssParser::getSimpleSelector(int p0)
-{
- int p = p0;
- int p2;
-
- DOMString str;
-
- p = skipwhite(p);
-
- int selectorItems = 0;
-
- XMLCh ch = get(p);
-
- //######################
- //# Note: do NOT skipwhite between items. Only within the
- //# pseudo function and attrib below
- //######################
-
- //#Element name 0 or 1
- if (uni_is_letter(ch))
- {
- p2 = getWord(p, str);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- error("null element name");
- return -1;
- }
- selectorItems++;
- p = p2;
- }
- else if (ch == '*')
- {
- str = "*";
- p++;
- selectorItems++;
- }
-
-
-
- //## HASH, CLASS, ATTRIB, PSEUDO (0 to many with elem name, 1 to many without)
- while (true)
- {
- XMLCh ch = get(p);
-
- //# HASH
- if (ch == '#')
- {
- p++;
- p2 = getWord(p, str);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- error("no name for hash");
- return -1;
- }
- p = p2;
- selectorItems++;
- }
-
- //# CLASS
- else if (ch == '.')
- {
- p++;
- p2 = getWord(p, str);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- error("no name for class");
- return -1;
- }
- p = p2;
- selectorItems++;
- }
-
- //# ATTRIB
- else if (ch == '[')
- {
- p++;
- p = skipwhite(p);
- p2 = getWord(p, str);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- error("no name for class");
- return -1;
- }
- p = skipwhite(p2);
- bool getRHS=false;
- if (match(p, "="))
- {
- p++;
- getRHS=true;
- }
- else if (match(p, "~="))
- {
- p+=2;
- getRHS=true;
- }
- else if (match(p, "|="))
- {
- p+=2;
- getRHS=true;
- }
- if (getRHS)
- {
- p = skipwhite(p);
- ch = get(p);
- if (uni_is_letter(ch))
- {
- p2 = getWord(p, str);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- error("null ident on rhs of attrib");
- return -1;
- }
- p = p2;
- }
- else if (ch == '\'' || ch =='"')
- {
- p2 = getQuoted(p, str);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- error("null literal string on rhs of attrib");
- return -1;
- }
- p = p2;
- }
- }//getRHS
- p = skipwhite(p);
- ch = get(p);
- if (ch != ']')
- {
- error("attrib needs closing ']'");
- //return -1;
- p = skipBlock(p);
- return p;
- }
- p++;
- selectorItems++;
- }
-
- //# PSEUDO
- else if (ch == ':')
- {
- p++;
- p2 = getWord(p, str);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- error("no name for pseudo");
- return -1;
- }
- p = p2;
- selectorItems++;
- ch = get(p);
- if (ch == '(')
- {
- p++;
- p = skipwhite(p);
- ch = get(p);
- if (uni_is_letter(ch))
- {
- p2 = getWord(p, str);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- error("null function parameter in pseudo");
- return -1;
- }
- p = skipwhite(p2);
- ch = get(p);
- }
- if (ch != ')')
- {
- error("function in pseudo needs ')'");
- return -1;
- }
- p++;
- }// ch==( -function-
- }//pseudo
-
- //# none of the above
- else
- {
- break;
- }
-
- }//while
-
-
- if (selectorItems > 0)
- return p;
- return p0;
-}
-
-/**
- * declaration
- * : property ':' S* expr prio?
- * | {empty}
- * ;
- */
-int CssParser::getDeclaration(int p0, CSSStyleDeclaration &declarationList)
-{
- int p = p0;
-
- //## PROPERTY
- p = skipwhite(p);
- XMLCh ch = get(p);
- if (!uni_is_letter(ch))
- return p0; //not me
- DOMString propName;
- int p2 = getWord(p, propName);
- if (p2<0)
- return -1;
-
- //## ':'
- p = skipwhite(p2);
- ch = get(p);
- if (ch != ':')
- {
- error("declaration requires ':' between name and value");
- return -1;
- }
- p++;
-
- //## EXPR
- p = skipwhite(p);
- p2 = getExpr(p);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- error("declaration requires value after ':'");
- return -1;
- }
- DOMString propVal;
- for (int i=p ; i<p2 ; i++) //get our substring
- propVal.push_back(get(i));
- printf("propVal:%s\n", propVal.c_str());
- p = p2;
-
- //## PRIO (optional)
- p = skipwhite(p);
- DOMString prio;
- p2 = getPrio(p, prio);
- if (p2<0)
- return -1;
- if (p2>p)
- {
- //do something
- p = p2;
- }
-
- return p;
-}
-
-/**
- * prio
- * : IMPORTANT_SYM S*
- * ;
- */
-int CssParser::getPrio(int p0, DOMString &val)
-{
- int p = p0;
-
- //## '!"
- p = skipwhite(p);
- XMLCh ch = get(p);
- if (ch != '!')
- return p0;
- p++;
-
- //## "important"
- p = skipwhite(p);
- if (!match(p, "important"))
- {
- error("priority symbol is 'important'");
- return -1;
- }
- p += 9;
- val = "important";
- return p;
-}
-
-/**
- * expr
- * : term [ operator term ]*
- * ;
- */
-int CssParser::getExpr(int p0)
-{
- int p = p0;
-
- //## TERM
- p = skipwhite(p);
- int p2 = getTerm(p);
- if (p2<0)
- return -1;
- if (p2<=p)
- return p0; //not me
- p = p2;
- while (p < parselen)
- {
- p = skipwhite(p);
- //#Operator. do this instead of getOperator()
- XMLCh ch = get(p);
- int visibleTerm = false;
- if (ch == '/')
- {
- visibleTerm = true;
- p++;
- }
- else if (ch == ',')
- {
- visibleTerm = true;
- p++;
- }
- else
- {
- //just space. this is allowable between terms,
- // so we still need to check for another term
- }
- p = skipwhite(p);
- p2 = getTerm(p);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- if (visibleTerm)
- {
- error("expression requires term after operator");
- return -1;
- }
- else
- {
- break;
- }
- }
- p = p2;
- }
-
- return p;
-}
-
-/**
- * term
- * : unary_operator?
- * [ NUMBER S* | PERCENTAGE S* | LENGTH S* | EMS S* | EXS S* | ANGLE S* |
- * TIME S* | FREQ S* | function ]
- * | STRING S* | IDENT S* | URI S* | hexcolor
- * ;
- */
-int CssParser::getTerm(int p0)
-{
- int p = p0;
- p = skipwhite(p);
- int unitType = CSSPrimitiveValue::CSS_UNKNOWN;
- //# Unary operator
- XMLCh ch = get(p);
- bool hasUnary = false;
- if (ch == '-')
- {
- p++;
- hasUnary = true;
- }
- else if (ch == '+')
- {
- p++;
- hasUnary = true;
- }
- //# NUMERIC
- double numVal;
- int p2 = getNumber(p, numVal);
- if (p2<0)
- return -1;
- if (p2>p)
- {
- p = p2;
- if (match(p, "%"))
- {
- unitType = CSSPrimitiveValue::CSS_PERCENTAGE;
- p++;
- }
- else if (match(p, "em"))
- {
- unitType = CSSPrimitiveValue::CSS_EMS;
- p+=2;
- }
- else if (match(p, "ex"))
- {
- unitType = CSSPrimitiveValue::CSS_EXS;
- p+=2;
- }
- else if (match(p, "px"))
- {
- unitType = CSSPrimitiveValue::CSS_PX;
- p+=2;
- }
- else if (match(p, "cm"))
- {
- unitType = CSSPrimitiveValue::CSS_CM;
- p+=2;
- }
- else if (match(p, "mm"))
- {
- unitType = CSSPrimitiveValue::CSS_MM;
- p+=2;
- }
- else if (match(p, "in"))
- {
- unitType = CSSPrimitiveValue::CSS_IN;
- p+=2;
- }
- else if (match(p, "pt"))
- {
- unitType = CSSPrimitiveValue::CSS_PT;
- p+=2;
- }
- else if (match(p, "pc"))
- {
- unitType = CSSPrimitiveValue::CSS_PC;
- p+=2;
- }
- else if (match(p, "deg"))
- {
- unitType = CSSPrimitiveValue::CSS_DEG;
- p+=3;
- }
- else if (match(p, "rad"))
- {
- unitType = CSSPrimitiveValue::CSS_RAD;
- p+=3;
- }
- else if (match(p, "grad"))
- {
- unitType = CSSPrimitiveValue::CSS_GRAD;
- p+=4;
- }
- else if (match(p, "ms"))
- {
- unitType = CSSPrimitiveValue::CSS_MS;
- p+=2;
- }
- else if (match(p, "s"))
- {
- unitType = CSSPrimitiveValue::CSS_S;
- p+=1;
- }
- else if (match(p, "Hz"))
- {
- unitType = CSSPrimitiveValue::CSS_HZ;
- p+=2;
- }
- else if (match(p, "kHz"))
- {
- unitType = CSSPrimitiveValue::CSS_KHZ;
- p+=2;
- }
- else if (uni_is_letter(get(p)))//some other string
- {
- DOMString suffix;
- p2 = getWord(p, suffix);
- if (p2<0)
- return -1;
- unitType = CSSPrimitiveValue::CSS_DIMENSION;
- p = p2;
- }
- else //plain number
- {
- unitType = CSSPrimitiveValue::CSS_NUMBER;
- }
- return p;
- }
-
- DOMString str;
-
- //## URI --do before function, as syntax is similar
- p2 = getUri(p, str);
- if (p2<0)
- return -1;
- if (p2>p)
- {
- if (hasUnary)
- {
- error("+ or - not allowed on URI");
- return -1;
- }
- p = p2;
- unitType = CSSPrimitiveValue::CSS_URI;
- return p;
- }
-
- //## FUNCTION
- p2 = getFunction(p);
- if (p2<0)
- return -1;
- if (p2>p)
- {
- p = p2;
- return p;
- }
-
- //## STRING
- ch = get(p);
- if (ch == '"' || ch == '\'')
- {
- p2 = getQuoted(p, str);
- if (p2<0)
- return -1;
- if (p2>p)
- {
- if (hasUnary)
- {
- error("+ or - not allowed on a string");
- return -1;
- }
- p = p2;
- unitType = CSSPrimitiveValue::CSS_STRING;
- return p;
- }
- }
-
- //## IDENT
- ch = get(p);
- if (uni_is_letter(ch))
- {
- p2 = getWord(p, str);
- if (p2<0)
- return -1;
- if (p2>p)
- {
- if (hasUnary)
- {
- error("+ or - not allowed on an identifier");
- return -1;
- }
- p = p2;
- unitType = CSSPrimitiveValue::CSS_IDENT;
- return p;
- }
- }
-
-
- //## HEXCOLOR
- p2 = getHexColor(p);
- if (p2<0)
- return -1;
- if (p2>p)
- {
- if (hasUnary)
- {
- error("+ or - not allowed on hex color");
- return -1;
- }
- p = p2;
- unitType = CSSPrimitiveValue::CSS_RGBCOLOR;
- return p;
- }
-
-
- return p0;
-}
-
-/**
- * function
- * : FUNCTION S* expr ')' S*
- * ;
- */
-int CssParser::getFunction(int p0)
-{
- int p = p0;
-
- //## IDENT + ( (both)
- DOMString name;
- p = skipwhite(p);
- int p2 = getWord(p, name);
- if (p2<0)
- return -1;
- if (p2<=p)
- return p0; //not me
- if (name == "uri" || name=="url")
- return p0; //not me
- p = skipwhite(p2);
- XMLCh ch = get(p);
- if (ch != '(')
- return p0; //still not me
- p++;
-
- //## EXPR
- p = skipwhite(p);
- p2 = getExpr(p);
- if (p2<0)
- return -1;
- if (p2<=p)
- {
- error("function requires expression");
- return -1;
- }
- p = p2;
-
- //## ')'
- p = skipwhite(p);
- ch = get(p);
- if (ch != ')')
- {
- error("function requires closing ')'");
- return -1;
- }
- p++;
- p = skipwhite(p);
-
- return p;
-}
-
-/**
- * There is a constraint on the color that it must
- * have either 3 or 6 hex-digits (i.e., [0-9a-fA-F])
- * after the "#"; e.g., "#000" is OK, but "#abcd" is not.
- * hexcolor
- * : HASH S*
- * ;
- */
-int CssParser::getHexColor(int p0)
-{
- int p = p0;
-
- //## '#'
- p = skipwhite(p);
- if (!match(p, "#"))
- return p0;
- p++;
-
- //## HEX
- DOMString hex;
- long hexVal = 0;
- while (p < parselen)
- {
- XMLCh b = get(p);
- if (b>='0' && b<='9')
- {
- hexVal = (hexVal << 4) + (b - '0');
- hex.push_back(b);
- p++;
- }
- else if (b>='a' && b<='f')
- {
- hexVal = (hexVal << 4) + (b - 'a' + 10);
- hex.push_back(b);
- p++;
- }
- else if (b>='A' && b<='F')
- {
- hexVal = (hexVal << 4) + (b - 'A' + 10);
- hex.push_back(b);
- p++;
- }
- else
- {
- break;
- }
- }
-
- if (hex.size() != 3 && hex.size() != 6)
- {
- error("exactly 3 or 6 hex digits are required after '#'");
- return -1;
- }
-
- return p;
-}
-
-
-
-/**
- *
- */
-bool CssParser::parse(const DOMString &str)
-{
- /*
- int len = str.size();
- for (int i=0 ; i<len ; i++)
- {
- XMLCh ch = str[i];
- if (ch == '\\' && i<(len-1)) //escape!
- {
- i++;
- }
- else
- parsebuf.push_back(ch);
- }
- */
- parsebuf = str;
-
- parselen = parsebuf.size();
- //printf("==============================\n%s\n========================\n", str.c_str());
-
- lastPosition = 0;
-
- int p = getStyleSheet(0);
- if (p < parselen)
- {
- error("Not everything parsed");
- return false;
- }
-
- return true;
-}
-
-
-/**
- *
- */
-bool CssParser::parseFile(const DOMString &fileName)
-{
- DOMString tmp = fileName;
- char *fname = (char *)tmp.c_str();
- FILE *f = fopen(fname, "r");
- if (!f)
- {
- printf("Could not open %s for reading\n", fname);
- return false;
- }
-
- DOMString str;
- while (!feof(f))
- {
- int ch = fgetc(f);
- if (ch<0)
- break;
- str.push_back((XMLCh)ch);
- }
- fclose(f);
-
- bool ret = parse(str);
-
- return ret;
-}
-
-
-
-
-
-
-
-} // namespace css
-} // namespace dom
-} // namespace w3c
-} // namespace org
-
-
-#ifdef TEST
-
-int main(int argc, char **argv)
-{
- org::w3c::dom::css::CssParser parser;
- char *fileName;
- fileName = "001.css";
- //fileName = "acid.css";
- //fileName = "base.css";
- //fileName = "inkscape.css";
- //fileName = "meyerweb.css";
- if (!parser.parseFile(fileName))
- {
- printf("Test failed\n");
- return 1;
- }
- return 0;
-}
-
-#endif /* TEST */
-
-//#########################################################################
-//# E N D O F F I L E
-//#########################################################################
-