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

📄 ael.flex

📁 asterisk 是一个很有知名度开源软件
💻 FLEX
📖 第 1 页 / 共 2 页
字号:
/* * Asterisk -- An open source telephony toolkit. * * Copyright (C) 2006, Digium, Inc. * * Steve Murphy <murf@parsetree.com> * * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. *//*! \file * * \brief Flex scanner description of tokens used in AEL2 . * *//* * Start with flex options: * * %x describes the contexts we have: paren, semic and argg, plus INITIAL */%x paren semic argg  comment curlystate wordstate brackstate/* prefix used for various globally-visible functions and variables. * This renames also yywrap, but since we do not use it, we just * add option noyywrap to remove it. */%option prefix="ael_yy"%option noyywrap 8bit/* I specify this option to suppress flex generating code with ECHO  in it. This generates compiler warnings in some systems; We've  seen the fwrite generate Unused variable warnings with 4.1.2 gcc.  Some systems have tweaked flex ECHO macro to keep the compiler  happy.  To keep the warning message from getting output, I added  a default rule at the end of the patterns section */%option nodefault/* yyfree normally just frees its arg. It can be null sometimes,   which some systems will complain about, so, we'll define our own version */%option noyyfree/* batch gives a bit more performance if we are using it in * a non-interactive mode. We probably don't care much. */%option batch/* outfile is the filename to be used instead of lex.yy.c */%option outfile="ael_lex.c"/* * These are not supported in flex 2.5.4, but we need them * at the moment: * reentrant produces a thread-safe parser. Not 100% sure that * we require it, though. * bison-bridge passes an additional yylval argument to yylex(). * bison-locations is probably not needed. */%option reentrant%option bison-bridge%option bison-locations%{#include "asterisk.h"ASTERISK_FILE_VERSION(__FILE__, "$Revision: 162272 $")#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include <glob.h>#if !defined(GLOB_ABORTED)#define GLOB_ABORTED GLOB_ABEND#endif#include "asterisk/logger.h"#include "asterisk/utils.h"#include "asterisk/lock.h"#include "asterisk/hashtab.h"#include "ael/ael.tab.h"#include "asterisk/ael_structs.h"/* * A stack to keep track of matching brackets ( [ { } ] ) */static char pbcstack[400];	/* XXX missing size checks */static int pbcpos = 0;static void pbcpush(char x);static int pbcpop(char x);static int parencount = 0;/* * A similar stack to keep track of matching brackets ( [ { } ] ) in word tokens surrounded by ${ ... } */static char pbcstack2[400];	/* XXX missing size checks */static int pbcpos2 = 0;static void pbcpush2(char x);static int pbcpop2(char x);static int parencount2 = 0;/* * A similar stack to keep track of matching brackets ( [ { } ] ) in word tokens surrounded by $[ ... ] */static char pbcstack3[400];	/* XXX missing size checks */static int pbcpos3 = 0;static void pbcpush3(char x);static int pbcpop3(char x);static int parencount3 = 0;/* * current line, column and filename, updated as we read the input. */static int my_lineno = 1;	/* current line in the source */static int my_col = 1;		/* current column in the source */char *my_file = 0;		/* used also in the bison code */char *prev_word;		/* XXX document it */#define MAX_INCLUDE_DEPTH 50/* * flex is not too smart, and generates global functions * without prototypes so the compiler may complain. * To avoid that, we declare the prototypes here, * even though these functions are not used. */int ael_yyget_column  (yyscan_t yyscanner);void ael_yyset_column (int  column_no , yyscan_t yyscanner);int ael_yyparse (struct parse_io *);/* * A stack to process include files. * As we switch into the new file we need to store the previous * state to restore it later. */struct stackelement {	char *fname;	int lineno;	int colno;	glob_t globbuf;        /* the current globbuf */	int globbuf_pos;   /* where we are in the current globbuf */	YY_BUFFER_STATE bufstate;};static struct stackelement  include_stack[MAX_INCLUDE_DEPTH];static int include_stack_index = 0;static void setup_filestack(char *fnamebuf, int fnamebuf_siz, glob_t *globbuf, int globpos, yyscan_t xscan, int create);/* * if we use the @n feature of bison, we must supply the start/end * location of tokens in the structure pointed by yylloc. * Simple tokens are just assumed to be on the same line, so * the line number is constant, and the column is incremented * by the length of the token. */#ifdef FLEX_BETA	/* set for 2.5.33 *//* compute the total number of lines and columns in the text * passed as argument. */static void pbcwhere(const char *text, int *line, int *col ){	int loc_line = *line;	int loc_col = *col;	char c;	while ( (c = *text++) ) {		if ( c == '\t' ) {			loc_col += 8 - (loc_col % 8);		} else if ( c == '\n' ) {			loc_line++;			loc_col = 1;		} else			loc_col++;	}	*line = loc_line;	*col = loc_col;}#define	STORE_POS do {							\		yylloc->first_line = yylloc->last_line = my_lineno;	\		yylloc->first_column=my_col;				\		yylloc->last_column=my_col+yyleng-1;			\		my_col+=yyleng;						\	} while (0)#define	STORE_LOC do {					\		yylloc->first_line = my_lineno;		\		yylloc->first_column=my_col;		\		pbcwhere(yytext, &my_lineno, &my_col);	\		yylloc->last_line = my_lineno;		\		yylloc->last_column = my_col - 1;	\	} while (0)#else#define	STORE_POS#define	STORE_LOC#endif%}KEYWORD     (context|abstract|extend|macro|globals|local|ignorepat|switch|if|ifTime|random|regexten|hint|else|goto|jump|return|break|continue|for|while|case|default|pattern|catch|switches|eswitches|includes)NOPARENS	([^()\[\]\{\}]|\\[()\[\]\{\}])*NOARGG		([^(),\{\}\[\]]|\\[,()\[\]\{\}])*NOSEMIC		([^;()\{\}\[\]]|\\[;()\[\]\{\}])*HIBIT		[\x80-\xff]%%\{		{ STORE_POS; return LC;}\}		{ STORE_POS; return RC;}\(		{ STORE_POS; return LP;}\)		{ STORE_POS; return RP;}\;		{ STORE_POS; return SEMI;}\=		{ STORE_POS; return EQ;}\,		{ STORE_POS; return COMMA;}\:		{ STORE_POS; return COLON;}\&		{ STORE_POS; return AMPER;}\|		{ STORE_POS; return BAR;}\=\>		{ STORE_POS; return EXTENMARK;}\@		{ STORE_POS; return AT;}\/\/[^\n]*	{/*comment*/}context		{ STORE_POS; return KW_CONTEXT;}abstract	{ STORE_POS; return KW_ABSTRACT;}extend		{ STORE_POS; return KW_EXTEND;}macro		{ STORE_POS; return KW_MACRO;};globals		{ STORE_POS; return KW_GLOBALS;}local		{ STORE_POS; return KW_LOCAL;}ignorepat	{ STORE_POS; return KW_IGNOREPAT;}switch		{ STORE_POS; return KW_SWITCH;}if		{ STORE_POS; return KW_IF;}ifTime		{ STORE_POS; return KW_IFTIME;}random		{ STORE_POS; return KW_RANDOM;}regexten	{ STORE_POS; return KW_REGEXTEN;}hint		{ STORE_POS; return KW_HINT;}else		{ STORE_POS; return KW_ELSE;}goto		{ STORE_POS; return KW_GOTO;}jump		{ STORE_POS; return KW_JUMP;}return		{ STORE_POS; return KW_RETURN;}break		{ STORE_POS; return KW_BREAK;}continue	{ STORE_POS; return KW_CONTINUE;}for		{ STORE_POS; return KW_FOR;}while		{ STORE_POS; return KW_WHILE;}case		{ STORE_POS; return KW_CASE;}default		{ STORE_POS; return KW_DEFAULT;}pattern		{ STORE_POS; return KW_PATTERN;}catch		{ STORE_POS; return KW_CATCH;}switches	{ STORE_POS; return KW_SWITCHES;}eswitches	{ STORE_POS; return KW_ESWITCHES;}includes	{ STORE_POS; return KW_INCLUDES;}"/*"            { BEGIN(comment); my_col += 2; }<comment>[^*\n]*	{ my_col += yyleng; }<comment>[^*\n]*\n	{ ++my_lineno; my_col=1;}<comment>"*"+[^*/\n]*	{ my_col += yyleng; }<comment>"*"+[^*/\n]*\n 	{ ++my_lineno; my_col=1;}<comment>"*/"		{ my_col += 2; BEGIN(INITIAL); } /* the nice thing about comments is that you know exactly what ends them */\n		{ my_lineno++; my_col = 1; }[ ]+		{ my_col += yyleng; }[\t]+		{ my_col += (yyleng*8)-(my_col%8); }({KEYWORD}?[-a-zA-Z0-9'"_/.\<\>\*\+!$#\[\]]|{HIBIT}|(\\.)|(\$\{)|(\$\[)) {       /* boy did I open a can of worms when I changed the lexical token "word".   	  	 all the above keywords can be used as a beginning to a "word".-		 before, a "word" would match a longer sequence than the above	 	     keywords, and all would be well. But now "word" is a single char			     and feeds into a statemachine sort of sequence from there on. So...		 I added the {KEYWORD}? to the beginning of the word match sequence */		if (!strcmp(yytext,"${")) {		   	parencount2 = 0;			pbcpos2 = 0;			pbcpush2('{');	/* push '{' so the last pcbpop (parencount2 = -1) will succeed */			BEGIN(curlystate);			yymore();		} else if (!strcmp(yytext,"$[")) {		   	parencount3 = 0;			pbcpos3 = 0;			pbcpush3('[');	/* push '[' so the last pcbpop (parencount3 = -1) will succeed */			BEGIN(brackstate);			yymore();		} else {		    BEGIN(wordstate);			yymore();		}	}<wordstate>[-a-zA-Z0-9'"_/.\<\>\*\+!$#\[\]] { yymore(); /* Keep going */ }<wordstate>{HIBIT} { yymore(); /* Keep going */ }<wordstate>(\\.)  { yymore(); /* Keep Going */ }<wordstate>(\$\{)  { /* the beginning of a ${} construct. prepare and pop into curlystate */	   	parencount2 = 0;		pbcpos2 = 0;		pbcpush2('{');	/* push '{' so the last pcbpop (parencount2 = -1) will succeed */		BEGIN(curlystate);		yymore();	}<wordstate>(\$\[)  { /* the beginning of a $[] construct. prepare and pop into brackstate */	   	parencount3 = 0;		pbcpos3 = 0;		pbcpush3('[');	/* push '[' so the last pcbpop (parencount3 = -1) will succeed */		BEGIN(brackstate);		yymore();	}<wordstate>([^a-zA-Z0-9\x80-\xff\x2d'"_/.\<\>\*\+!$#\[\]]) {		/* a non-word constituent char, like a space, tab, curly, paren, etc */		char c = yytext[yyleng-1];		STORE_POS;		yylval->str = malloc(yyleng);		strncpy(yylval->str, yytext, yyleng);		yylval->str[yyleng-1] = 0;		unput(c);  /* put this ending char back in the stream */		BEGIN(0);		return word;	}<curlystate>{NOPARENS}\}	{		if ( pbcpop2('}') ) {	/* error */			STORE_LOC;			ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched ')' in expression: %s !\n", my_file, my_lineno, my_col, yytext);			BEGIN(0);			yylval->str = malloc(yyleng+1);			strncpy(yylval->str, yytext, yyleng);			yylval->str[yyleng] = 0;			return word;		}		parencount2--;		if ( parencount2 >= 0) {			yymore();		} else {			BEGIN(wordstate); /* Finished with the current ${} construct. Return to word gathering state */			yymore();		}	}<curlystate>{NOPARENS}[\(\[\{]	{ 		char c = yytext[yyleng-1];		if (c == '{')			parencount2++;		pbcpush2(c);		yymore();	}<curlystate>{NOPARENS}[\]\)]	{ 		char c = yytext[yyleng-1];		if ( pbcpop2(c))  { /* error */			STORE_LOC;			ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched '%c' in expression!\n",				my_file, my_lineno, my_col, c);			BEGIN(0);			yylval->str = malloc(yyleng+1);			strncpy(yylval->str, yytext, yyleng);			yylval->str[yyleng] = 0;			return word;		}		yymore();	}<brackstate>{NOPARENS}\]	{		if ( pbcpop3(']') ) {	/* error */			STORE_LOC;			ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched ')' in expression: %s !\n", my_file, my_lineno, my_col, yytext);			BEGIN(0);			yylval->str = malloc(yyleng+1);			strncpy(yylval->str, yytext, yyleng);			yylval->str[yyleng] = 0;			return word;		}		parencount3--;		if ( parencount3 >= 0) {			yymore();		} else {			BEGIN(wordstate); /* Finished with the current ${} construct. Return to word gathering state */			yymore();		}	}<brackstate>{NOPARENS}[\(\[\{]	{ 		char c = yytext[yyleng-1];		if (c == '[')			parencount3++;		pbcpush3(c);		yymore();	}<brackstate>{NOPARENS}[\}\)]	{ 		char c = yytext[yyleng-1];		if ( pbcpop3(c))  { /* error */			STORE_LOC;			ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched '%c' in expression!\n",				my_file, my_lineno, my_col, c);			BEGIN(0);			yylval->str = malloc(yyleng+1);			strncpy(yylval->str, yytext, yyleng);			yylval->str[yyleng] = 0;			return word;		}		yymore();	}	/*	 * context used for arguments of if_head, random_head, switch_head,	 * for (last statement), while (XXX why not iftime_head ?).	 * End with the matching parentheses.	 * A comma at the top level is valid here, unlike in argg where it	 * is an argument separator so it must be returned as a token.	 */<paren>{NOPARENS}\)	{		if ( pbcpop(')') ) {	/* error */			STORE_LOC;			ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched ')' in expression: %s !\n", my_file, my_lineno, my_col, yytext);			BEGIN(0);			yylval->str = malloc(yyleng+1);			strncpy(yylval->str, yytext, yyleng);			yylval->str[yyleng] = 0;			prev_word = 0;			return word;		}		parencount--;		if ( parencount >= 0) {			yymore();		} else {			STORE_LOC;			yylval->str = malloc(yyleng);			strncpy(yylval->str, yytext, yyleng);			yylval->str[yyleng-1] = 0;			unput(')');			BEGIN(0);			return word;		}	}<paren>{NOPARENS}[\(\[\{]	{		char c = yytext[yyleng-1];		if (c == '(')			parencount++;		pbcpush(c);		yymore();	}<paren>{NOPARENS}[\]\}]	{		char c = yytext[yyleng-1];		if ( pbcpop(c))  { /* error */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -