class Gherkin::CLexer::Cs
Public Class Methods
new(p1)
click to toggle source
static VALUE CLexer_init(VALUE self, VALUE listener)
{
lexer_state *lxr;
rb_iv_set(self, "@listener", listener);
lxr = NULL;
DATA_GET(self, lexer_state, lxr);
lexer_init(lxr);
return self;
}
Public Instance Methods
scan(p1)
click to toggle source
static VALUE CLexer_scan(VALUE self, VALUE input)
{
VALUE input_copy;
char *data;
size_t len;
VALUE listener = rb_iv_get(self, "@listener");
lexer_state *lexer;
lexer = NULL;
DATA_GET(self, lexer_state, lexer);
input_copy = rb_str_dup(input);
rb_str_append(input_copy, rb_str_new2("\n%_FEATURE_END_%"));
data = RSTRING_PTR(input_copy);
len = RSTRING_LEN(input_copy);
if (len == 0) {
rb_raise(rb_eGherkinLexingError, "No content to lex.");
} else {
const char *p, *pe, *eof;
int cs = 0;
VALUE current_row = Qnil;
p = data;
pe = data + len;
eof = pe;
assert(*pe == '\0' && "pointer does not end on NULL");
#line 1119 "ext/gherkin_lexer_cs/gherkin_lexer_cs.c"
{
cs = lexer_start;
}
#line 425 "ragel/i18n/cs.c.rl"
#line 1126 "ext/gherkin_lexer_cs/gherkin_lexer_cs.c"
{
int _klen;
unsigned int _trans;
const char *_acts;
unsigned int _nacts;
const char *_keys;
if ( p == pe )
goto _test_eof;
if ( cs == 0 )
goto _out;
_resume:
_keys = _lexer_trans_keys + _lexer_key_offsets[cs];
_trans = _lexer_index_offsets[cs];
_klen = _lexer_single_lengths[cs];
if ( _klen > 0 ) {
const char *_lower = _keys;
const char *_mid;
const char *_upper = _keys + _klen - 1;
while (1) {
if ( _upper < _lower )
break;
_mid = _lower + ((_upper-_lower) >> 1);
if ( (*p) < *_mid )
_upper = _mid - 1;
else if ( (*p) > *_mid )
_lower = _mid + 1;
else {
_trans += (unsigned int)(_mid - _keys);
goto _match;
}
}
_keys += _klen;
_trans += _klen;
}
_klen = _lexer_range_lengths[cs];
if ( _klen > 0 ) {
const char *_lower = _keys;
const char *_mid;
const char *_upper = _keys + (_klen<<1) - 2;
while (1) {
if ( _upper < _lower )
break;
_mid = _lower + (((_upper-_lower) >> 1) & ~1);
if ( (*p) < _mid[0] )
_upper = _mid - 2;
else if ( (*p) > _mid[1] )
_lower = _mid + 2;
else {
_trans += (unsigned int)((_mid - _keys)>>1);
goto _match;
}
}
_trans += _klen;
}
_match:
cs = _lexer_trans_targs[_trans];
if ( _lexer_trans_actions[_trans] == 0 )
goto _again;
_acts = _lexer_actions + _lexer_trans_actions[_trans];
_nacts = (unsigned int) *_acts++;
while ( _nacts-- > 0 )
{
switch ( *_acts++ )
{
case 0:
#line 83 "ragel/i18n/cs.c.rl"
{
MARK(content_start, p);
lexer->current_line = lexer->line_number;
lexer->start_col = lexer->content_start - lexer->last_newline - (lexer->keyword_end - lexer->keyword_start) + 2;
}
break;
case 1:
#line 89 "ragel/i18n/cs.c.rl"
{
MARK(content_start, p);
}
break;
case 2:
#line 93 "ragel/i18n/cs.c.rl"
{
lexer->current_line = lexer->line_number;
lexer->start_col = p - data - lexer->last_newline;
}
break;
case 3:
#line 98 "ragel/i18n/cs.c.rl"
{
int len = LEN(content_start, PTR_TO(final_newline));
int type_len = LEN(docstring_content_type_start, PTR_TO(docstring_content_type_end));
if (len < 0) len = 0;
if (type_len < 0) len = 0;
store_docstring_content(listener, lexer->start_col, PTR_TO(docstring_content_type_start), type_len, PTR_TO(content_start), len, lexer->current_line);
}
break;
case 4:
#line 108 "ragel/i18n/cs.c.rl"
{
MARK(docstring_content_type_start, p);
}
break;
case 5:
#line 112 "ragel/i18n/cs.c.rl"
{
MARK(docstring_content_type_end, p);
}
break;
case 6:
#line 116 "ragel/i18n/cs.c.rl"
{
STORE_KW_END_CON(feature);
}
break;
case 7:
#line 120 "ragel/i18n/cs.c.rl"
{
STORE_KW_END_CON(background);
}
break;
case 8:
#line 124 "ragel/i18n/cs.c.rl"
{
STORE_KW_END_CON(scenario);
}
break;
case 9:
#line 128 "ragel/i18n/cs.c.rl"
{
STORE_KW_END_CON(scenario_outline);
}
break;
case 10:
#line 132 "ragel/i18n/cs.c.rl"
{
STORE_KW_END_CON(examples);
}
break;
case 11:
#line 136 "ragel/i18n/cs.c.rl"
{
store_kw_con(listener, "step",
PTR_TO(keyword_start), LEN(keyword_start, PTR_TO(keyword_end)),
PTR_TO(content_start), LEN(content_start, p),
lexer->current_line);
}
break;
case 12:
#line 143 "ragel/i18n/cs.c.rl"
{
STORE_ATTR(comment);
lexer->mark = 0;
}
break;
case 13:
#line 148 "ragel/i18n/cs.c.rl"
{
STORE_ATTR(tag);
lexer->mark = 0;
}
break;
case 14:
#line 153 "ragel/i18n/cs.c.rl"
{
lexer->line_number += 1;
MARK(final_newline, p);
}
break;
case 15:
#line 158 "ragel/i18n/cs.c.rl"
{
MARK(last_newline, p + 1);
}
break;
case 16:
#line 162 "ragel/i18n/cs.c.rl"
{
if (lexer->mark == 0) {
MARK(mark, p);
}
}
break;
case 17:
#line 168 "ragel/i18n/cs.c.rl"
{
MARK(keyword_end, p);
MARK(keyword_start, PTR_TO(mark));
MARK(content_start, p + 1);
lexer->mark = 0;
}
break;
case 18:
#line 175 "ragel/i18n/cs.c.rl"
{
MARK(content_end, p);
}
break;
case 19:
#line 179 "ragel/i18n/cs.c.rl"
{
p = p - 1;
lexer->current_line = lexer->line_number;
current_row = rb_ary_new();
}
break;
case 20:
#line 185 "ragel/i18n/cs.c.rl"
{
MARK(content_start, p);
}
break;
case 21:
#line 189 "ragel/i18n/cs.c.rl"
{
VALUE re_pipe, re_newline, re_backslash;
VALUE con = ENCODED_STR_NEW(PTR_TO(content_start), LEN(content_start, p));
rb_funcall(con, rb_intern("strip!"), 0);
re_pipe = rb_reg_regcomp(rb_str_new2("\\\\\\|"));
re_newline = rb_reg_regcomp(rb_str_new2("\\\\n"));
re_backslash = rb_reg_regcomp(rb_str_new2("\\\\\\\\"));
rb_funcall(con, rb_intern("gsub!"), 2, re_pipe, rb_str_new2("|"));
rb_funcall(con, rb_intern("gsub!"), 2, re_newline, rb_str_new2("\n"));
rb_funcall(con, rb_intern("gsub!"), 2, re_backslash, rb_str_new2("\\"));
rb_ary_push(current_row, con);
}
break;
case 22:
#line 203 "ragel/i18n/cs.c.rl"
{
rb_funcall(listener, rb_intern("row"), 2, current_row, INT2FIX(lexer->current_line));
}
break;
case 23:
#line 207 "ragel/i18n/cs.c.rl"
{
int line;
if (cs < lexer_first_final) {
size_t count = 0;
VALUE newstr_val;
char *newstr;
int newstr_count = 0;
size_t len;
const char *buff;
if (lexer->last_newline != 0) {
len = LEN(last_newline, eof);
buff = PTR_TO(last_newline);
} else {
len = strlen(data);
buff = data;
}
/* Allocate as a ruby string so that it gets cleaned up by GC */
newstr_val = rb_str_new(buff, len);
newstr = RSTRING_PTR(newstr_val);
for (count = 0; count < len; count++) {
if(buff[count] == 10) {
newstr[newstr_count] = '\0'; /* terminate new string at first newline found */
break;
} else {
if (buff[count] == '%') {
newstr[newstr_count++] = buff[count];
newstr[newstr_count] = buff[count];
} else {
newstr[newstr_count] = buff[count];
}
}
newstr_count++;
}
line = lexer->line_number;
lexer_init(lexer); /* Re-initialize so we can scan again with the same lexer */
raise_lexer_error(newstr, line);
} else {
rb_funcall(listener, rb_intern("eof"), 0);
}
}
break;
#line 1416 "ext/gherkin_lexer_cs/gherkin_lexer_cs.c"
}
}
_again:
if ( cs == 0 )
goto _out;
if ( ++p != pe )
goto _resume;
_test_eof: {}
if ( p == eof )
{
const char *__acts = _lexer_actions + _lexer_eof_actions[cs];
unsigned int __nacts = (unsigned int) *__acts++;
while ( __nacts-- > 0 ) {
switch ( *__acts++ ) {
case 23:
#line 207 "ragel/i18n/cs.c.rl"
{
int line;
if (cs < lexer_first_final) {
size_t count = 0;
VALUE newstr_val;
char *newstr;
int newstr_count = 0;
size_t len;
const char *buff;
if (lexer->last_newline != 0) {
len = LEN(last_newline, eof);
buff = PTR_TO(last_newline);
} else {
len = strlen(data);
buff = data;
}
/* Allocate as a ruby string so that it gets cleaned up by GC */
newstr_val = rb_str_new(buff, len);
newstr = RSTRING_PTR(newstr_val);
for (count = 0; count < len; count++) {
if(buff[count] == 10) {
newstr[newstr_count] = '\0'; /* terminate new string at first newline found */
break;
} else {
if (buff[count] == '%') {
newstr[newstr_count++] = buff[count];
newstr[newstr_count] = buff[count];
} else {
newstr[newstr_count] = buff[count];
}
}
newstr_count++;
}
line = lexer->line_number;
lexer_init(lexer); /* Re-initialize so we can scan again with the same lexer */
raise_lexer_error(newstr, line);
} else {
rb_funcall(listener, rb_intern("eof"), 0);
}
}
break;
#line 1479 "ext/gherkin_lexer_cs/gherkin_lexer_cs.c"
}
}
}
_out: {}
}
#line 426 "ragel/i18n/cs.c.rl"
assert(p <= pe && "data overflow after parsing execute");
assert(lexer->content_start <= len && "content starts after data end");
assert(lexer->mark < len && "mark is after data end");
/* Reset lexer by re-initializing the whole thing */
lexer_init(lexer);
if (cs == lexer_error) {
rb_raise(rb_eGherkinLexingError, "Invalid format, lexing fails.");
} else {
return Qtrue;
}
}
}