示例#1
0
文件: tlexer.c 项目: fy0/tinyre
int tre_lexer_next(tre_Lexer* lex) {
    int len;
    uint32_t code;
    uint32_t* name;
    if (lex->scur == lex->slen) {
        lex->token.value = TK_END;
        return 0;
    }
    code = char_next(lex);
    bool is_lastone = (lex->scur == lex->slen);

    switch (lex->state) {
        case 0: // NORMAL STATE
            if (token_check(code)) {
                lex->token.extra.code = 0;
                lex->token.value = code; // token val is it's own ascii.

                switch (code) {
                    case '[':
                        lex->state = 1;
                        if ((!is_lastone) && char_lookahead(lex) == '^') {
                            lex->token.extra.code = 1;
                        }
                        break;
                    case '{': {
                        int count;
                        int scur_bak = lex->scur;
                        int llimit = 0, rlimit = -1;

                        // read left limit a{1
                        llimit = read_int(lex, 0, &count);
                        if (count == 0) goto __bad_token;
                        code = char_nextn(lex, count+1);

                        // read comma a{1,
                        if ((char)code == ',') {
                            //char_next(lex);
                        } else if ((char)code == '}') {
                            rlimit = llimit;
                            goto __write_code;
                        } else {
                            // falied, rollback
                            goto __bad_token;
                        }

                        // read left limit a{1, 2
                        rlimit = read_int(lex, 0, &count);
                        code = char_nextn(lex, count+1);

                        // read right brace a{1,2} or a{1,}
                        if ((char)code == '}') {
                            // ok, rlimit is -1
                        } else {
                            // falied, rollback
                            goto __bad_token;
                        }

                    __write_code:
                        lex->token.extra.code = llimit;
                        lex->token.extra.code2 = rlimit;
                        break;

                    __bad_token:
                        lex->token.value = TK_CHAR;
                        lex->token.extra.code = '{';
                        lex->scur = scur_bak;
                        break;
                    }
                    case '(': {
                        code = char_lookahead(lex);
                        // if next char is not ?
                        if (code != '?') {
                            lex->token.extra.group_type = GT_NORMAL;
                            lex->token.extra.group_name = NULL;
                            break;
                        } else {
                            code = char_nextn(lex, 2);
                            switch (code) {
                                case '#': { // just comment
                                    bool is_escape = false;
                                    code = char_next(lex);
                                    while (!(!is_escape && code == ')')) {
                                        code = char_next(lex);
                                        if (is_escape) is_escape = false;
                                        if (code == '\\') is_escape = true;
                                        if (code == '\0') return ERR_LEXER_UNBALANCED_PARENTHESIS;
                                    }
                                    lex->token.value = TK_COMMENT;
                                    break;
                                }
                                case ':': lex->token.extra.group_type = GT_NONGROUPING; break;
                                case '=': lex->token.extra.group_type = GT_IF_MATCH; break;
                                case '!': lex->token.extra.group_type = GT_IF_NOT_MATCH; break;
                                case '(':
                                    // code for conditional backref
                                    name = read_group_name(lex, ')', &len);
                                    if (name) {
                                        code = char_nextn(lex, len);
                                        lex->token.extra.group_type = GT_BACKREF_CONDITIONAL_GROUPNAME;
                                        lex->token.extra.group_name = name;
                                        lex->token.extra.group_name_len = len;
                                    } else {
                                        int i = read_int(lex, ')', &len);
                                        if (i == -1) {
                                            return ERR_LEXER_INVALID_GROUP_NAME_OR_INDEX;
                                        } else {
                                            code = char_nextn(lex, len);
                                            lex->token.extra.group_type = GT_BACKREF_CONDITIONAL_INDEX;
                                            lex->token.extra.index = i;
                                        }
                                    }
                                    code = char_next(lex);
                                    break;
                                case 'P':
                                    // group name
                                    code = char_lookahead(lex);
                                    if (code == '<') {
                                        code = char_next(lex);
                                        name = read_group_name(lex, '>', &len);
                                        if (!name) return ERR_LEXER_BAD_GROUP_NAME;
                                        code = char_nextn(lex, len+1); // name and '>'

                                        lex->token.extra.group_type = GT_NORMAL;
                                        lex->token.extra.group_name = name;
                                        lex->token.extra.group_name_len = len;
                                    } else if (code == '=') {
                                        // code for back reference (?P=)
                                        code = char_next(lex);
                                        name = read_group_name(lex, ')', &len);
                                        if (!name) return ERR_LEXER_BAD_GROUP_NAME_IN_BACKREF;
                                        code = char_nextn(lex, len); // skip name

                                        lex->token.extra.group_type = GT_BACKREF;
                                        lex->token.extra.group_name = name;
                                        lex->token.extra.group_name_len = len;
                                    } else {
                                        return ERR_LEXER_UNKNOW_SPECIFIER;
                                    }
                                    break;
                                case '<':
                                    code = char_next(lex);
                                    if (code == '=') {
                                        lex->token.extra.group_type = GT_IF_PRECEDED_BY;
                                    } else if (code == '!') {
                                        lex->token.extra.group_type = GT_IF_NOT_PRECEDED_BY;
                                    } else {
                                        return ERR_LEXER_UNKNOW_SPECIFIER;
                                    }
                                    break;
                                default:
                                    if (char_to_flag(code)) {
                                        int flag = 0;
                                        while (true) {
                                            flag = char_to_flag(code);
                                            if (flag) lex->extra_flag |= flag;
                                            else break;
                                            code = char_next(lex);
                                        }
                                    } else {
                                        return ERR_LEXER_UNEXPECTED_END_OF_PATTERN;
                                    }
                                    lex->token.value = TK_NOP;
                                    break;
                            }
                        }
                    }
                };
            } else {
                int ret = token_char_accept(lex, code, true);
                if (ret) return ret;
            }
            break;
        case 1: { // [...]
            bool is_escape = code == '\\';
            int ret = token_char_accept(lex, code, false);
            if (ret) return ret;

            if (!is_escape && lex->token.value == TK_CHAR) {
                // end the state
                if (code == ']') {
                    lex->state = 0;
                    lex->token.value = ']';
                    break;
                }
            }

            // [a-z] grammar
            code = char_lookahead(lex);
            if (code == '-') {
                uint32_t code2 = char_lookaheadn(lex, 2);
                // [a-]
                if (code2 == ']') break;

                // [\s-1] -> error
                if (lex->token.value == TK_CHAR_SPE) {
                    return ERR_LEXER_BAD_CHARACTER_RANGE;
                }

                // [a-z]
                code2 = lex->token.extra.code;
                code = char_nextn(lex, 2);
                ret = token_char_accept(lex, code, false);
                if (ret) return ret;

                // [1-\s] -> error
                if (lex->token.value == TK_CHAR_SPE) {
                    return ERR_LEXER_BAD_CHARACTER_RANGE;
                }

                // [z-a] -> error
                if (lex->token.extra.code < code2) {
                    return ERR_LEXER_BAD_CHARACTER_RANGE;
                }

                // everything is ok
                lex->token.value = '-';
                lex->token.extra.code2 = lex->token.extra.code;
                lex->token.extra.code = code2;
            }
            break;
        }
    }
    return 0;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//controltype_label_message
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int controltype_label_message(control *c, int tokencount, char *tokens[])
{
	// token strings

	enum
	{
		T_NONE          = 0,
		T_STYLE         ,
		T_VALIGN        ,
		T_HALIGN        ,
		T_HASTITLE      ,
		T_LOCKPOS       ,

		T_PLUGINLOAD    ,
		T_PLUGINUNLOAD  ,
		T_PLUGINSETPOS  ,
		T_PLUGINSHOW    ,

		T_PLUGINABOUT
	};

	extern char szWPStyle [];

	static struct token_check controltype_label_property_tokens[] =
	{
		{ szWPStyle,            T_STYLE         , 1 },
		{ "VAlign",             T_VALIGN        , 1 },
		{ "HAlign",             T_HALIGN        , 1 },
		{ "HasTitleBar",        T_HASTITLE      , 1 },
		{ "IsLocked",           T_LOCKPOS       , 1 },
		{ NULL }
	};

	static struct token_check controltype_label_plugin_property_tokens[] =
	{
		{ "IsVisible",          T_PLUGINSHOW    , 1 },
		{ "Position",           T_PLUGINSETPOS  , 2 },
		{ NULL }
	};

	static struct token_check controltype_label_plugin_tokens[] =
	{
		{ "Load",               T_PLUGINLOAD    , 1 },
		{ "Unload",             T_PLUGINUNLOAD  , 1 },
		{ "About",              T_PLUGINABOUT   , 0 },
		{ szBActionPluginSetProperty, (UINT_PTR)controltype_label_plugin_property_tokens  , 2 },
		{ NULL }
	};

	static struct token_check controltype_label_message_tokens[] =
	{
		{ szBActionSetControlProperty, (UINT_PTR)controltype_label_property_tokens, 2 },
		{ szBActionPlugin, (UINT_PTR)controltype_label_plugin_tokens, 2 },
		{ NULL }
	};

	// -----------------
	//Get the details
	controltype_label_details *details = (controltype_label_details *) c->controldetails;

	//If set control details
	int i;
	int curtok = 2;
	switch (token_check(controltype_label_message_tokens, &curtok, tokencount, tokens))
	{
		// -----------------
	case T_STYLE:
		if (-1 != (i = get_string_index(tokens[curtok], szStyleNames)))
		{
			c->windowptr->style = i;
			style_draw_invalidate(c);
			return 0;
		}
		break;

		// -----------------
	case T_HALIGN:
		if (-1 != (i = get_string_index(tokens[curtok], label_haligns)))
		{
			details->halign = i;
			controltype_label_updatesettings(details);
			style_draw_invalidate(c);
			return 0;
		}
		break;

		// -----------------
	case T_VALIGN:
		if (-1 != (i = get_string_index(tokens[curtok], label_valigns)))
		{
			details->valign = i;
			controltype_label_updatesettings(details);
			style_draw_invalidate(c);
			return 0;
		}
		break;

		// -----------------
	case T_HASTITLE:
		if (details->is_frame && config_set_bool(tokens[curtok], &details->has_titlebar))
		{
			style_draw_invalidate(c);
			return 0;
		}
		break;

		// -----------------
	case T_LOCKPOS:
		if (details->is_frame && config_set_bool(tokens[curtok], &details->is_locked))
			return 0;
		break;

		// -----------------
	case T_PLUGINLOAD:
		if (details->is_frame)
		{
			char *plugin_name = tokens[curtok];
			if (0 == strcmp(plugin_name, "*browse*"))
			{
				// "open file" dialog
				plugin_name = dialog_file("Plugins\0*.dll\0", "Add Plugin" , NULL, ".dll", false);
				if (NULL == plugin_name)
				{
					//message_override = true;
					return 2;
				}
			}
			ModuleInfo * m = loadPlugin(&details->module_info, c->windowptr->hwnd, plugin_name);
			if (m)
			{
				variables_set(false, "LastPlugin", m->module_name);
				return 0;
			}
		}
		break;

		// -----------------
	case T_PLUGINUNLOAD:
		if (unloadPlugin(&details->module_info, tokens[curtok]))
			return 0;
		break;

		// -----------------
	case T_PLUGINSETPOS:
	{
		int x, y;
		if (config_set_int(tokens[curtok], &x)
				&& config_set_int(tokens[1+curtok], &y)
				&& plugin_setpos(details->plugin_info, tokens[-2+curtok], x, y)
		   )
			return 0;

		return 0; // dont generate an error here...
	}
	break;

	// -----------------
	case T_PLUGINSHOW:
	{
		bool show;
		if (plugin_getset_show_state(details->plugin_info, tokens[-2+curtok],
									 config_set_bool(tokens[curtok], &show) ? show : 2)
		   )
			return 0;

		return 0; // dont generate an error here...
	}
	break;

	// -----------------
	case T_PLUGINABOUT:
	{
		aboutPlugins(details->module_info, c->controlname);
		return 0;
	}
	break;

	// -----------------
	//Must be an agent message
	default:
		return agent_controlmessage(c, tokencount, tokens, CONTROLTYPE_LABEL_AGENT_COUNT, details->agents, controltype_label_agentnames, controltype_label_agenttypes);
	}
	return 1;
}