📄 grammar.c
字号:
}
eat_spaces (&t);
s->m_spec_type = st_string;
}
else if (*t == '.')
{
byte *keyword = NULL;
/* skip the dot */
t++;
if (get_identifier (&t, &keyword))
{
spec_destroy (&s);
return 1;
}
eat_spaces (&t);
/* .true */
if (str_equal ((byte *) "true", keyword))
{
s->m_spec_type = st_true;
}
/* .false */
else if (str_equal ((byte *) "false", keyword))
{
s->m_spec_type = st_false;
}
/* .debug */
else if (str_equal ((byte *) "debug", keyword))
{
s->m_spec_type = st_debug;
}
/* .loop */
else if (str_equal ((byte *) "loop", keyword))
{
if (get_identifier (&t, &s->m_string))
{
mem_free ((void **) (void *) &keyword);
spec_destroy (&s);
return 1;
}
eat_spaces (&t);
s->m_spec_type = st_identifier_loop;
}
mem_free ((void **) (void *) &keyword);
}
else
{
if (get_identifier (&t, &s->m_string))
{
spec_destroy (&s);
return 1;
}
eat_spaces (&t);
s->m_spec_type = st_identifier;
}
if (get_error (&t, &s->m_errtext, maps))
{
spec_destroy (&s);
return 1;
}
if (get_emits (&t, &s->m_emits, mapb))
{
spec_destroy (&s);
return 1;
}
*text = t;
*sp = s;
return 0;
}
/*
returns 0 on success,
returns 1 otherwise,
*/
static int get_rule (const byte **text, rule **ru, map_str *maps, map_byte *mapb)
{
const byte *t = *text;
rule *r = NULL;
rule_create (&r);
if (r == NULL)
return 1;
if (get_spec (&t, &r->m_specs, maps, mapb))
{
rule_destroy (&r);
return 1;
}
while (*t != ';')
{
byte *op = NULL;
spec *sp = NULL;
/* skip the dot that precedes "and" or "or" */
t++;
/* read "and" or "or" keyword */
if (get_identifier (&t, &op))
{
rule_destroy (&r);
return 1;
}
eat_spaces (&t);
if (r->m_oper == op_none)
{
/* .and */
if (str_equal ((byte *) "and", op))
r->m_oper = op_and;
/* .or */
else
r->m_oper = op_or;
}
mem_free ((void **) (void *) &op);
if (get_spec (&t, &sp, maps, mapb))
{
rule_destroy (&r);
return 1;
}
spec_append (&r->m_specs, sp);
}
/* skip the semicolon */
t++;
eat_spaces (&t);
*text = t;
*ru = r;
return 0;
}
/*
returns 0 on success,
returns 1 otherwise,
*/
static int update_dependency (map_rule *mapr, byte *symbol, rule **ru)
{
if (map_rule_find (&mapr, symbol, ru))
return 1;
(**ru).m_referenced = 1;
return 0;
}
/*
returns 0 on success,
returns 1 otherwise,
*/
static int update_dependencies (dict *di, map_rule *mapr, byte **syntax_symbol,
byte **string_symbol, map_byte *regbytes)
{
rule *rulez = di->m_rulez;
/* update dependecies for the root and lexer symbols */
if (update_dependency (mapr, *syntax_symbol, &di->m_syntax) ||
(*string_symbol != NULL && update_dependency (mapr, *string_symbol, &di->m_string)))
return 1;
mem_free ((void **) syntax_symbol);
mem_free ((void **) string_symbol);
/* update dependecies for the rest of the rules */
while (rulez)
{
spec *sp = rulez->m_specs;
/* iterate through all the specifiers */
while (sp)
{
/* update dependency for identifier */
if (sp->m_spec_type == st_identifier || sp->m_spec_type == st_identifier_loop)
{
if (update_dependency (mapr, sp->m_string, &sp->m_rule))
return 1;
mem_free ((void **) &sp->m_string);
}
/* some errtexts reference to a rule */
if (sp->m_errtext && sp->m_errtext->m_token_name)
{
if (update_dependency (mapr, sp->m_errtext->m_token_name, &sp->m_errtext->m_token))
return 1;
mem_free ((void **) &sp->m_errtext->m_token_name);
}
/* update dependency for condition */
if (sp->m_cond)
{
int i;
for (i = 0; i < 2; i++)
if (sp->m_cond->m_operands[i].m_type == cot_regbyte)
{
sp->m_cond->m_operands[i].m_regbyte = map_byte_locate (®bytes,
sp->m_cond->m_operands[i].m_regname);
if (sp->m_cond->m_operands[i].m_regbyte == NULL)
return 1;
mem_free ((void **) &sp->m_cond->m_operands[i].m_regname);
}
}
/* update dependency for all .load instructions */
if (sp->m_emits)
{
emit *em = sp->m_emits;
while (em != NULL)
{
if (em->m_emit_dest == ed_regbyte)
{
em->m_regbyte = map_byte_locate (®bytes, em->m_regname);
if (em->m_regbyte == NULL)
return 1;
mem_free ((void **) &em->m_regname);
}
em = em->m_next;
}
}
sp = sp->next;
}
rulez = rulez->next;
}
/* check for unreferenced symbols */
rulez = di->m_rulez;
while (rulez != NULL)
{
if (!rulez->m_referenced)
{
map_rule *ma = mapr;
while (ma)
{
if (ma->data == rulez)
{
set_last_error (UNREFERENCED_IDENTIFIER, str_duplicate (ma->key), -1);
return 1;
}
ma = ma->next;
}
}
rulez = rulez->next;
}
return 0;
}
static int satisfies_condition (cond *co, regbyte_ctx *ctx)
{
byte values[2];
int i;
if (co == NULL)
return 1;
for (i = 0; i < 2; i++)
switch (co->m_operands[i].m_type)
{
case cot_byte:
values[i] = co->m_operands[i].m_byte;
break;
case cot_regbyte:
values[i] = regbyte_ctx_extract (&ctx, co->m_operands[i].m_regbyte);
break;
}
switch (co->m_type)
{
case ct_equal:
return values[0] == values[1];
case ct_not_equal:
return values[0] != values[1];
}
return 0;
}
static void free_regbyte_ctx_stack (regbyte_ctx *top, regbyte_ctx *limit)
{
while (top != limit)
{
regbyte_ctx *rbc = top->m_prev;
regbyte_ctx_destroy (&top);
top = rbc;
}
}
typedef enum match_result_
{
mr_not_matched, /* the examined string does not match */
mr_matched, /* the examined string matches */
mr_error_raised, /* mr_not_matched + error has been raised */
mr_dont_emit, /* used by identifier loops only */
mr_internal_error /* an internal error has occured such as out of memory */
} match_result;
/*
This function does the main job. It parses the text and generates output data.
*/
static match_result match (dict *di, const byte *text, unsigned int *index, rule *ru, barray **ba,
int filtering_string, regbyte_ctx **rbc)
{
unsigned int ind = *index;
match_result status = mr_not_matched;
spec *sp = ru->m_specs;
regbyte_ctx *ctx = *rbc;
/* for every specifier in the rule */
while (sp)
{
unsigned int i, len, save_ind = ind;
barray *array = NULL;
if (satisfies_condition (sp->m_cond, ctx))
{
switch (sp->m_spec_type)
{
case st_identifier:
barray_create (&array);
if (array == NULL)
{
free_regbyte_ctx_stack (ctx, *rbc);
return mr_internal_error;
}
status = match (di, text, &ind, sp->m_rule, &array, filtering_string, &ctx);
if (status == mr_internal_error)
{
free_regbyte_ctx_stack (ctx, *rbc);
barray_destroy (&array);
return mr_internal_error;
}
break;
case st_string:
len = str_length (sp->m_string);
/* prefilter the stream */
if (!filtering_string && di->m_string)
{
barray *ba;
unsigned int filter_index = 0;
match_result result;
regbyte_ctx *null_ctx = NULL;
barray_create (&ba);
if (ba == NULL)
{
free_regbyte_ctx_stack (ctx, *rbc);
return mr_internal_error;
}
result = match (di, text + ind, &filter_index, di->m_string, &ba, 1, &null_ctx);
if (result == mr_internal_error)
{
free_regbyte_ctx_stack (ctx, *rbc);
barray_destroy (&ba);
return mr_internal_error;
}
if (result != mr_matched)
{
barray_destroy (&ba);
status = mr_not_matched;
break;
}
barray_destroy (&ba);
if (filter_index != len || !str_equal_n (sp->m_string, text + ind, len))
{
status = mr_not_matched;
break;
}
status = mr_matched;
ind += len;
}
else
{
status = mr_matched;
for (i = 0; status == mr_matched && i < len; i++)
if (text[ind + i] != sp->m_string[i])
status = mr_not_matched;
if (status == mr_matched)
ind += len;
}
break;
case st_byte:
status = text[ind] == *sp->m_byte ? mr_matched : mr_not_matched;
if (status == mr_matched)
ind++;
break;
case st_byte_range:
status = (text[ind] >= sp->m_byte[0] && text[ind] <= sp->m_byte[1]) ?
mr_matched : mr_not_matched;
if (status == mr_matched)
ind++;
break;
case st_true:
status = mr_matched;
break;
case st_false:
status = mr_not_matched;
break;
case st_debug:
status = ru->m_oper == op_and ? mr_matched : mr_not_matched;
break;
case st_identifier_loop:
barray_create (&array);
if (array == NULL)
{
free_regbyte_ctx_stack (ctx, *rbc);
return mr_internal_error;
}
status = mr_dont_emit;
for (;;)
{
match_result result;
save_ind = ind;
result = match (di, text, &ind, sp->m_rule, &array, filtering_string, &ctx);
if (result == mr_error_raised)
{
status = result;
break;
}
else if (result == mr_matched)
{
if (barray_push (ba, sp->m_emits, text[ind - 1], save_ind, &ctx) ||
barray_append (ba, &array))
{
free_regbyte_ctx_stack (ctx, *rbc);
barray_destroy (&array);
return mr_internal_error;
}
barray_destroy (&array);
barray_create (&array);
if (array == NULL)
{
free_regbyte_ctx_stack (ctx, *rbc);
return mr_internal_error;
}
}
else if (result == mr_internal_error)
{
free_regbyte_ctx_stack (ctx, *rbc);
barray_destroy (&array);
return mr_internal_error;
}
else
break;
}
break;
}
}
else
{
status = mr_not_matched;
}
if (status == mr_error_raised)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -