diff options
-rw-r--r-- | src/lex/lex.c | 42 | ||||
-rw-r--r-- | test/data/lex/INDEX | 1 | ||||
-rw-r--r-- | test/data/lex/regression.dat | 48 |
3 files changed, 79 insertions, 12 deletions
diff --git a/src/lex/lex.c b/src/lex/lex.c index 8f85d25..460cca0 100644 --- a/src/lex/lex.c +++ b/src/lex/lex.c @@ -130,7 +130,7 @@ static inline css_error emitToken(css_lexer *lexer, css_token_type type, css_token **token); static inline css_error AtKeyword(css_lexer *lexer, css_token **token); -static inline css_error CDCOrIdentOrFunction(css_lexer *lexer, +static inline css_error CDCOrIdentOrFunctionOrNPD(css_lexer *lexer, css_token **token); static inline css_error CDO(css_lexer *lexer, css_token **token); static inline css_error Comment(css_lexer *lexer, css_token **token); @@ -285,7 +285,7 @@ css_error css_lexer_get_token(css_lexer *lexer, css_token **token) case sCDO: return CDO(lexer, token); case sCDC: - return CDCOrIdentOrFunction(lexer, token); + return CDCOrIdentOrFunctionOrNPD(lexer, token); case sS: return S(lexer, token); case sCOMMENT: @@ -541,7 +541,7 @@ css_error AtKeyword(css_lexer *lexer, css_token **token) return emitToken(lexer, CSS_TOKEN_ATKEYWORD, token); } -css_error CDCOrIdentOrFunction(css_lexer *lexer, css_token **token) +css_error CDCOrIdentOrFunctionOrNPD(css_lexer *lexer, css_token **token) { css_token *t = &lexer->token; uintptr_t cptr; @@ -553,10 +553,14 @@ css_error CDCOrIdentOrFunction(css_lexer *lexer, css_token **token) /* CDC = "-->" * IDENT = [-]? nmstart nmchar* * FUNCTION = [-]? nmstart nmchar* '(' + * NUMBER = num = [-+]? ([0-9]+ | [0-9]* '.' [0-9]+) + * PERCENTAGE = num '%' + * DIMENSION = num ident * * The first dash has been consumed. Thus, we must consume the next * character in the stream. If it's a dash, then we're dealing with - * CDC. Otherwise, we're dealing with IDENT/FUNCTION. + * CDC. If it's a digit or dot, then we're dealing with NPD. + * Otherwise, we're dealing with IDENT/FUNCTION. */ switch (lexer->substate) { @@ -573,6 +577,16 @@ css_error CDCOrIdentOrFunction(css_lexer *lexer, css_token **token) c = *((uint8_t *) cptr); + if (isDigit(c) || c == '.') { + /* NPD */ + APPEND(lexer, cptr, clen); + lexer->state = sNUMBER; + lexer->substate = 0; + /* Abuse "first" to store first non-sign character */ + lexer->context.first = c; + return NumberOrPercentageOrDimension(lexer, token); + } + if (c != '-' && !startNMStart(c)) { /* Can only be CHAR */ return emitToken(lexer, CSS_TOKEN_CHAR, token); @@ -975,11 +989,12 @@ css_error NumberOrPercentageOrDimension(css_lexer *lexer, css_token **token) enum { Initial = 0, Dot = 1, MoreDigits = 2, Suffix = 3, NMChars = 4, Escape = 5 }; - /* NUMBER = num = [0-9]+ | [0-9]* '.' [0-9]+ + /* NUMBER = num = [-+]? ([0-9]+ | [0-9]* '.' [0-9]+) * PERCENTAGE = num '%' * DIMENSION = num ident * - * The first digit, or '.' has been consumed. + * The sign, or sign and first digit or dot, + * or first digit, or '.' has been consumed. */ switch (lexer->substate) { @@ -998,7 +1013,8 @@ css_error NumberOrPercentageOrDimension(css_lexer *lexer, css_token **token) return CSS_NEEDDATA; if (cptr == PARSERUTILS_INPUTSTREAM_EOF) { - if (t->data.len == 1 && lexer->context.first == '.') + if (t->data.len == 1 && (lexer->context.first == '.' || + lexer->context.first == '+')) return emitToken(lexer, CSS_TOKEN_CHAR, token); else return emitToken(lexer, CSS_TOKEN_NUMBER, @@ -1042,7 +1058,8 @@ css_error NumberOrPercentageOrDimension(css_lexer *lexer, css_token **token) return CSS_NEEDDATA; if (cptr == PARSERUTILS_INPUTSTREAM_EOF) { - if (t->data.len == 1 && lexer->context.first == '.') + if (t->data.len == 1 && (lexer->context.first == '.' || + lexer->context.first == '+')) return emitToken(lexer, CSS_TOKEN_CHAR, token); else return emitToken(lexer, CSS_TOKEN_NUMBER, @@ -1051,8 +1068,9 @@ css_error NumberOrPercentageOrDimension(css_lexer *lexer, css_token **token) c = *((uint8_t *) cptr); - /* A solitary '.' is a CHAR, not numeric */ - if (t->data.len == 1 && lexer->context.first == '.') + /* A solitary '.' or '+' is a CHAR, not numeric */ + if (t->data.len == 1 && (lexer->context.first == '.' || + lexer->context.first == '+')) return emitToken(lexer, CSS_TOKEN_CHAR, token); if (c == '%') { @@ -1183,7 +1201,7 @@ start: return Hash(lexer, token); case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': - case '.': + case '.': case '+': lexer->state = sNUMBER; lexer->substate = 0; lexer->context.first = c; @@ -1195,7 +1213,7 @@ start: case '-': lexer->state = sCDC; lexer->substate = 0; - return CDCOrIdentOrFunction(lexer, token); + return CDCOrIdentOrFunctionOrNPD(lexer, token); case ' ': case '\t': case '\r': case '\n': case '\f': lexer->state = sS; lexer->substate = 0; diff --git a/test/data/lex/INDEX b/test/data/lex/INDEX index a3439f2..2e1e066 100644 --- a/test/data/lex/INDEX +++ b/test/data/lex/INDEX @@ -4,3 +4,4 @@ tests1.dat Basic tests tests2.dat More complicated tests +regression.dat Regression tests diff --git a/test/data/lex/regression.dat b/test/data/lex/regression.dat new file mode 100644 index 0000000..1798631 --- /dev/null +++ b/test/data/lex/regression.dat @@ -0,0 +1,48 @@ +#data +-1 +#expected +NUMBER:-1 +S +EOF +#reset + +#data ++1 +#expected +NUMBER:+1 +S +EOF +#reset + +#data +-1.0 +#expected +NUMBER:-1.0 +S +EOF +#reset + +#data ++1.0 +#expected +NUMBER:+1.0 +S +EOF +#reset + +#data +-.5 +#expected +NUMBER:-.5 +S +EOF +#reset + +#data ++.5 +#expected +NUMBER:+.5 +S +EOF +#reset + |