?? ael.y
字號:
} | goto_word COLON word { if (asprintf(&($$), "%s:%s", $1, $3) < 0) { ast_log(LOG_WARNING, "asprintf() failed\n"); $$ = NULL; } else { free($1); free($3); } } ;switch_statement : KW_SWITCH test_expr LC case_statements RC { $$ = npval2(PV_SWITCH, &@1, &@5); $$->u1.str = $2; $$->u2.statements = $4; set_dads($$,$4);} ;/* * Definition of a statememt in our language */statement : LC statements RC { $$ = npval2(PV_STATEMENTBLOCK, &@1, &@3); $$->u1.list = $2; set_dads($$,$2);} | assignment { $$ = $1; } | local_assignment { $$ = $1; } | KW_GOTO target SEMI { $$ = npval2(PV_GOTO, &@1, &@3); $$->u1.list = $2;} | KW_JUMP jumptarget SEMI { $$ = npval2(PV_GOTO, &@1, &@3); $$->u1.list = $2;} | word COLON { $$ = npval2(PV_LABEL, &@1, &@2); $$->u1.str = $1; } | KW_FOR LP {reset_semicount(parseio->scanner);} word SEMI {reset_semicount(parseio->scanner);} word SEMI {reset_parencount(parseio->scanner);} word RP statement { /* XXX word_list maybe ? */ $$ = npval2(PV_FOR, &@1, &@12); $$->u1.for_init = $4; $$->u2.for_test=$7; $$->u3.for_inc = $10; $$->u4.for_statements = $12; set_dads($$,$12);} | KW_WHILE test_expr statement { $$ = npval2(PV_WHILE, &@1, &@3); $$->u1.str = $2; $$->u2.statements = $3; set_dads($$,$3);} | switch_statement { $$ = $1; } | AMPER macro_call SEMI { $$ = update_last($2, &@2); } | application_call SEMI { $$ = update_last($1, &@2); } | word SEMI { $$= npval2(PV_APPLICATION_CALL, &@1, &@2); $$->u1.str = $1;} | application_call EQ {reset_semicount(parseio->scanner);} word SEMI { char *bufx; int tot=0; pval *pptr; $$ = npval2(PV_VARDEC, &@1, &@5); $$->u2.val=$4; /* rebuild the original string-- this is not an app call, it's an unwrapped vardec, with a func call on the LHS */ /* string to big to fit in the buffer? */ tot+=strlen($1->u1.str); for(pptr=$1->u2.arglist;pptr;pptr=pptr->next) { tot+=strlen(pptr->u1.str); tot++; /* for a sep like a comma */ } tot+=4; /* for safety */ bufx = calloc(1, tot); strcpy(bufx,$1->u1.str); strcat(bufx,"("); /* XXX need to advance the pointer or the loop is very inefficient */ for (pptr=$1->u2.arglist;pptr;pptr=pptr->next) { if ( pptr != $1->u2.arglist ) strcat(bufx,","); strcat(bufx,pptr->u1.str); } strcat(bufx,")");#ifdef AAL_ARGCHECK if ( !ael_is_funcname($1->u1.str) ) ast_log(LOG_WARNING, "==== File: %s, Line %d, Cols: %d-%d: Function call? The name %s is not in my internal list of function names\n", my_file, @1.first_line, @1.first_column, @1.last_column, $1->u1.str);#endif $$->u1.str = bufx; destroy_pval($1); /* the app call it is not, get rid of that chain */ prev_word = 0; } | KW_BREAK SEMI { $$ = npval2(PV_BREAK, &@1, &@2); } | KW_RETURN SEMI { $$ = npval2(PV_RETURN, &@1, &@2); } | KW_CONTINUE SEMI { $$ = npval2(PV_CONTINUE, &@1, &@2); } | if_like_head statement opt_else { $$ = update_last($1, &@2); $$->u2.statements = $2; set_dads($$,$2); $$->u3.else_statements = $3;set_dads($$,$3);} | SEMI { $$=0; } ;opt_else : KW_ELSE statement { $$ = $2; } | { $$ = NULL ; } target : goto_word { $$ = nword($1, &@1); } | goto_word BAR goto_word { $$ = nword($1, &@1); $$->next = nword($3, &@3); } | goto_word COMMA goto_word { $$ = nword($1, &@1); $$->next = nword($3, &@3); } | goto_word BAR goto_word BAR goto_word { $$ = nword($1, &@1); $$->next = nword($3, &@3); $$->next->next = nword($5, &@5); } | goto_word COMMA goto_word COMMA goto_word { $$ = nword($1, &@1); $$->next = nword($3, &@3); $$->next->next = nword($5, &@5); } | KW_DEFAULT BAR goto_word BAR goto_word { $$ = nword(strdup("default"), &@1); $$->next = nword($3, &@3); $$->next->next = nword($5, &@5); } | KW_DEFAULT COMMA goto_word COMMA goto_word { $$ = nword(strdup("default"), &@1); $$->next = nword($3, &@3); $$->next->next = nword($5, &@5); } ;opt_pri : /* empty */ { $$ = strdup("1"); } | COMMA word { $$ = $2; } ;/* XXX please document the form of jumptarget */jumptarget : goto_word opt_pri { /* ext[, pri] default 1 */ $$ = nword($1, &@1); $$->next = nword($2, &@2); } /* jump extension[,priority][@context] */ | goto_word opt_pri AT context_name { /* context, ext, pri */ $$ = nword($4, &@4); $$->next = nword($1, &@1); $$->next->next = nword($2, &@2); } ;macro_call : word LP {reset_argcount(parseio->scanner);} eval_arglist RP { /* XXX original code had @2 but i think we need @5 */ $$ = npval2(PV_MACRO_CALL, &@1, &@5); $$->u1.str = $1; $$->u2.arglist = $4;} | word LP RP { $$= npval2(PV_MACRO_CALL, &@1, &@3); $$->u1.str = $1; } ;/* XXX application_call_head must be revised. Having 'word LP { ...' * just as above should work fine, however it gives a different result. */application_call_head: word LP {reset_argcount(parseio->scanner);} { if (strcasecmp($1,"goto") == 0) { $$ = npval2(PV_GOTO, &@1, &@2); free($1); /* won't be using this */ ast_log(LOG_WARNING, "==== File: %s, Line %d, Cols: %d-%d: Suggestion: Use the goto statement instead of the Goto() application call in AEL.\n", my_file, @1.first_line, @1.first_column, @1.last_column ); } else { $$= npval2(PV_APPLICATION_CALL, &@1, &@2); $$->u1.str = $1; } } ;application_call : application_call_head eval_arglist RP { $$ = update_last($1, &@3); if( $$->type == PV_GOTO ) $$->u1.list = $2; else $$->u2.arglist = $2; } | application_call_head RP { $$ = update_last($1, &@2); } ;opt_word : word { $$ = $1 } | { $$ = strdup(""); } ;eval_arglist : word_list { $$ = nword($1, &@1); } | /*nothing! */ { $$= npval(PV_WORD,0/*@1.first_line*/,0/*@1.last_line*/,0/* @1.first_column*/, 0/*@1.last_column*/); $$->u1.str = strdup(""); } | eval_arglist COMMA opt_word { $$ = linku1($1, nword($3, &@3)); } ;case_statements: /* empty */ { $$ = NULL; } | case_statement case_statements { $$ = linku1($1, $2); } ;case_statement: KW_CASE word COLON statements { $$ = npval2(PV_CASE, &@1, &@3); /* XXX 3 or 4 ? */ $$->u1.str = $2; $$->u2.statements = $4; set_dads($$,$4);} | KW_DEFAULT COLON statements { $$ = npval2(PV_DEFAULT, &@1, &@3); $$->u1.str = NULL; $$->u2.statements = $3;set_dads($$,$3);} | KW_PATTERN word COLON statements { $$ = npval2(PV_PATTERN, &@1, &@4); /* XXX@3 or @4 ? */ $$->u1.str = $2; $$->u2.statements = $4;set_dads($$,$4);} ;macro_statements: /* empty */ { $$ = NULL; } | macro_statement macro_statements { $$ = linku1($1, $2); } ;macro_statement : statement {$$=$1;} | includes { $$=$1;} | KW_CATCH word LC statements RC { $$ = npval2(PV_CATCH, &@1, &@5); $$->u1.str = $2; $$->u2.statements = $4; set_dads($$,$4);} ;switches : KW_SWITCHES LC switchlist RC { $$ = npval2(PV_SWITCHES, &@1, &@2); $$->u1.list = $3; set_dads($$,$3);} ;eswitches : KW_ESWITCHES LC switchlist RC { $$ = npval2(PV_ESWITCHES, &@1, &@2); $$->u1.list = $3; set_dads($$,$3);} ;switchlist : /* empty */ { $$ = NULL; } | word SEMI switchlist { $$ = linku1(nword($1, &@1), $3); } | word AT word SEMI switchlist { char *x; if (asprintf(&x,"%s@%s", $1, $3) < 0) { ast_log(LOG_WARNING, "asprintf() failed\n"); $$ = NULL; } else { free($1); free($3); $$ = linku1(nword(x, &@1), $5); } } | error switchlist {$$=$2;} ;included_entry : context_name { $$ = nword($1, &@1); } | context_name BAR timespec { $$ = nword($1, &@1); $$->u2.arglist = $3; prev_word=0; /* XXX sure ? */ } ;/* list of ';' separated context names followed by optional timespec */includeslist : included_entry SEMI { $$ = $1; } | includeslist included_entry SEMI { $$ = linku1($1, $2); } | includeslist error {$$=$1;} ;includes : KW_INCLUDES LC includeslist RC { $$ = npval2(PV_INCLUDES, &@1, &@4); $$->u1.list = $3;set_dads($$,$3);} | KW_INCLUDES LC RC { $$ = npval2(PV_INCLUDES, &@1, &@3);} ;%%static char *token_equivs1[] ={ "AMPER", "AT", "BAR", "COLON", "COMMA", "EQ", "EXTENMARK", "KW_BREAK", "KW_CASE", "KW_CATCH", "KW_CONTEXT", "KW_CONTINUE", "KW_DEFAULT", "KW_ELSE", "KW_ESWITCHES", "KW_FOR", "KW_GLOBALS", "KW_GOTO", "KW_HINT", "KW_IFTIME", "KW_IF", "KW_IGNOREPAT", "KW_INCLUDES" "KW_JUMP", "KW_MACRO", "KW_PATTERN", "KW_REGEXTEN", "KW_RETURN", "KW_SWITCHES", "KW_SWITCH", "KW_WHILE", "LC", "LP", "RC", "RP", "SEMI",};static char *token_equivs2[] ={ "&", "@", "|", ":", ",", "=", "=>", "break", "case", "catch", "context", "continue", "default", "else", "eswitches", "for", "globals", "goto", "hint", "ifTime", "if", "ignorepat", "includes" "jump", "macro", "pattern", "regexten", "return", "switches", "switch", "while", "{", "(", "}", ")", ";",};static char *ael_token_subst(const char *mess){ /* calc a length, malloc, fill, and return; yyerror had better free it! */ int len=0,i; const char *p; char *res, *s,*t; int token_equivs_entries = sizeof(token_equivs1)/sizeof(char*); for (p=mess; *p; p++) { for (i=0; i<token_equivs_entries; i++) { if ( strncmp(p,token_equivs1[i],strlen(token_equivs1[i])) == 0 ) { len+=strlen(token_equivs2[i])+2; p += strlen(token_equivs1[i])-1; break; } } len++; } res = calloc(1, len+1); res[0] = 0; s = res; for (p=mess; *p;) { int found = 0; for (i=0; i<token_equivs_entries; i++) { if ( strncmp(p,token_equivs1[i],strlen(token_equivs1[i])) == 0 ) { *s++ = '\''; for (t=token_equivs2[i]; *t;) { *s++ = *t++; } *s++ = '\''; p += strlen(token_equivs1[i]); found = 1; break; } } if( !found ) *s++ = *p++; } *s++ = 0; return res;}void yyerror(YYLTYPE *locp, struct parse_io *parseio, char const *s){ char *s2 = ael_token_subst((char *)s); if (locp->first_line == locp->last_line) { ast_log(LOG_ERROR, "==== File: %s, Line %d, Cols: %d-%d: Error: %s\n", my_file, locp->first_line, locp->first_column, locp->last_column, s2); } else { ast_log(LOG_ERROR, "==== File: %s, Line %d Col %d to Line %d Col %d: Error: %s\n", my_file, locp->first_line, locp->first_column, locp->last_line, locp->last_column, s2); } free(s2); parseio->syntax_error_count++;}struct pval *npval(pvaltype type, int first_line, int last_line, int first_column, int last_column){ pval *z = calloc(1, sizeof(struct pval)); z->type = type; z->startline = first_line; z->endline = last_line; z->startcol = first_column; z->endcol = last_column; z->filename = strdup(my_file); return z;}static struct pval *npval2(pvaltype type, YYLTYPE *first, YYLTYPE *last){ return npval(type, first->first_line, last->last_line, first->first_column, last->last_column);}static struct pval *update_last(pval *obj, YYLTYPE *last){ obj->endline = last->last_line; obj->endcol = last->last_column; return obj;}/* frontend for npval to create a PV_WORD string from the given token */static pval *nword(char *string, YYLTYPE *pos){ pval *p = npval2(PV_WORD, pos, pos); if (p) p->u1.str = string; return p;}/* this routine adds a dad ptr to each element in the list */static void set_dads(struct pval *dad, struct pval *child_list){ struct pval *t; for(t=child_list;t;t=t->next) /* simple stuff */ t->dad = dad;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -