📄 ael.flex
字号:
/* * 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/* 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/* 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%{ASTERISK_FILE_VERSION(__FILE__, "$Revision: 59206 $")#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include "asterisk/logger.h"#include "asterisk/utils.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;/* * 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; YY_BUFFER_STATE bufstate;};static struct stackelement include_stack[MAX_INCLUDE_DEPTH];static int include_stack_index = 0;/* * 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%}NOPARENS ([^()\[\]\{\}]|\\[()\[\]\{\}])*NOARGG ([^(),\{\}\[\]]|\\[,()\[\]\{\}])*NOSEMIC ([^;()\{\}\[\]]|\\[;()\[\]\{\}])*%%\{ { 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;}macro { STORE_POS; return KW_MACRO;};globals { STORE_POS; return KW_GLOBALS;}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); }\n { my_lineno++; my_col = 1; }[ ]+ { my_col += yyleng; }[\t]+ { my_col += (yyleng*8)-(my_col%8); }[-a-zA-Z0-9'"_/.\<\>\*\+!$#\[\]][-a-zA-Z0-9'"_/.!\*\+\<\>\{\}$#\[\]]* { STORE_POS; yylval->str = strdup(yytext); prev_word = yylval->str; return word; } /* * 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 = strdup(yytext); prev_word = 0; return word; } parencount--; if ( parencount >= 0) { yymore(); } else { STORE_LOC; yylval->str = strdup(yytext); yylval->str[yyleng-1] = '\0'; /* trim trailing ')' */ 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 */ 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 = strdup(yytext); return word; } yymore(); } /* * handlers for arguments to a macro or application calls. * We enter this context when we find the initial '(' and * stay here until we close all matching parentheses, * and find the comma (argument separator) or the closing ')' * of the (external) call, which happens when parencount == 0 * before the decrement. */<argg>{NOARGG}[\(\[\{] { char c = yytext[yyleng-1]; if (c == '(') parencount++; pbcpush(c);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -