⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 grammar.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 5 页
字号:
        }
        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 (&regbytes,
                            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 (&regbytes, 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 + -