📄 grammar.c
字号:
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_resultmatch (dict *di, const byte *text, int *index, rule *ru, barray **ba, int filtering_string, regbyte_ctx **rbc){ 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) { 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; 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) { free_regbyte_ctx_stack (ctx, *rbc); barray_destroy (&array); return mr_error_raised; } if (ru->m_oper == op_and && status != mr_matched && status != mr_dont_emit) { free_regbyte_ctx_stack (ctx, *rbc); barray_destroy (&array); if (sp->m_errtext) { set_last_error (sp->m_errtext->m_text, error_get_token (sp->m_errtext, di, text, ind), ind); return mr_error_raised; } return mr_not_matched; } if (status == mr_matched) { if (sp->m_emits) if (barray_push (ba, sp->m_emits, text[ind - 1], save_ind, &ctx)) { free_regbyte_ctx_stack (ctx, *rbc); barray_destroy (&array); return mr_internal_error; } if (array) if (barray_append (ba, &array)) { free_regbyte_ctx_stack (ctx, *rbc); barray_destroy (&array); return mr_internal_error; } } barray_destroy (&array); /* if the rule operator is a logical or, we pick up the first matching specifier */ if (ru->m_oper == op_or && (status == mr_matched || status == mr_dont_emit)) { *index = ind; *rbc = ctx; return mr_matched; } sp = sp->next; } /* everything went fine - all specifiers match up */ if (ru->m_oper == op_and && (status == mr_matched || status == mr_dont_emit)) { *index = ind; *rbc = ctx; return mr_matched; } free_regbyte_ctx_stack (ctx, *rbc); return mr_not_matched;}static match_resultfast_match (dict *di, const byte *text, int *index, rule *ru, int *_PP, bytepool *_BP, int filtering_string, regbyte_ctx **rbc){ int ind = *index; int _P = filtering_string ? 0 : *_PP; int _P2; match_result status = mr_not_matched; spec *sp = ru->m_specs; regbyte_ctx *ctx = *rbc; /* for every specifier in the rule */ while (sp) { int i, len, save_ind = ind; _P2 = _P + (sp->m_emits ? emit_size (sp->m_emits) : 0); if (bytepool_reserve (_BP, _P2)) { free_regbyte_ctx_stack (ctx, *rbc); return mr_interna
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -