blob: 28a6f6257bbaf7548108ceeecbb56b4c8408b0ce [file] [log] [blame]
/*
Copyright 2002-2003 John Plevyak, All Rights Reserved
*/
#include "d.h"
int
scan_buffer(d_loc_t *loc, D_State *parse_state, ShiftResult *results) {
char *s = loc->s, *scol = 0;
int col = loc->col, collast = col, line = loc->line;
int nresults = 0, i, j;
D_Shift **shift = NULL;
if (parse_state->scan_kind != D_SCAN_LONGEST) {
/* all matches */
SB_uint8 *st = (SB_uint8*)parse_state->scanner_table;
SB_trans_uint8 *tst = (SB_trans_uint8*)parse_state->transition_table;
uint8 state = 0, last = state;
uint8 c;
uint32 sb, so;
c = (uint8)*s++;
while ((state = st[state].scanner_block[(sb = (c >> SCANNER_BLOCK_SHIFT))]
[(so = c & SCANNER_BLOCK_MASK)]))
{
state -= 1;
if (st[state].shift) {
last = state;
loc->s = s; collast = col; loc->line = line;
shift = parse_state->accepts_diff[tst[state].scanner_block[sb][so]];
for (; *shift; shift++) {
results[nresults].loc = *loc;
results[nresults++].shift = *shift;
}
}
if (c == '\n') { line++; col = 0; scol = s; } else col++;
c = (uint8)*s++;
}
loc->col = scol ? s - scol : -1;
shift = st[last].shift;
if (shift) {
loc->line = line;
for (; *shift; shift++) {
results[nresults].loc = *loc;
results[nresults++].shift = *shift;
}
}
if (nresults && parse_state->scan_kind == D_SCAN_MIXED) {
char *end = results[nresults-1].loc.s;
int longest = 0;
for (i = nresults - 1; i >= 0; i--) {
if (results[i].shift->shift_kind == D_SCAN_LONGEST)
longest = 1;
if (results[i].loc.s < end)
break;
}
if (!longest) {
/* only keep non-longest */
for (j = i; j >= 0; j--)
if (results[j].shift->shift_kind != D_SCAN_LONGEST) {
if (i != j)
results[i] = results[j];
i--;
}
nresults = nresults - i - 1;
if (i != -1)
memmove(&results[0], &results[i + 1], nresults * sizeof(results[0]));
} else {
/* keep only 'longest' */
i = 0;
for (j = 0; j < nresults; j++)
if (results[j].loc.s == end) {
if (i != j)
results[i] = results[j];
i++;
}
nresults = i;
}
}
return nresults;
} else {
/* longest match only */
switch (parse_state->scanner_size) {
case 1: {
SB_uint8 *st = (SB_uint8*)parse_state->scanner_table;
uint8 state = 0, last = state;
uint8 c;
c = (uint8)*s++;
while ((state = st[state].scanner_block[c >> SCANNER_BLOCK_SHIFT]
[c & SCANNER_BLOCK_MASK]))
{
state -= 1;
if (st[state].shift) {
last = state;
loc->s = s; collast = col; loc->line = line;
}
if (c == '\n') { line++; col = 0; scol = s; } else col++;
c = (uint8)*s++;
}
shift = st[last].shift;
break;
}
case 2: {
SB_uint16 *st = (SB_uint16*)parse_state->scanner_table;
uint16 state = 0, last = state;
uint8 c;
c = (uint8)*s++;
while ((state = st[state].scanner_block[c >> SCANNER_BLOCK_SHIFT]
[c & SCANNER_BLOCK_MASK]))
{
state -= 1;
if (st[state].shift) {
last = state;
loc->s = s; collast = col; loc->line = line;
}
if (c == '\n') { line++; col = 0; scol = s; } else col++;
c = (uint8)*s++;
}
shift = st[last].shift;
break;
}
case 4: {
SB_uint32 *st = (SB_uint32*)parse_state->scanner_table;
uint32 state = 0, last = state;
uint8 c;
c = (uint8)*s++;
while ((state = st[state].scanner_block[c >> SCANNER_BLOCK_SHIFT]
[c & SCANNER_BLOCK_MASK]))
{
state -= 1;
if (st[state].shift) {
last = state;
loc->s = s; collast = col; loc->line = line;
}
if (c == '\n') { line++; col = 0; scol = s; } else col++;
c = (uint8)*s++;
}
shift = st[last].shift;
break;
}
}
loc->col = scol ? s - scol : -1;
if (shift) {
loc->line = line;
for (; *shift; shift++) {
results[nresults].loc = *loc;
results[nresults++].shift = *shift;
}
}
return nresults;
}
}