📄 vbs_grammar.y
字号:
%{// the grammar descript for the subset of VBScript language// written by me.xinxin@gmail.com%}%name-prefix="vbs_"%pure-parser%locations%debug%error-verbose%parse-param { Cvbs_context* cnt }%lex-param { Cvbs_context* cnt }%{#include <string>#include <iostream>#include "../inc/tracelog.h"#include "vbs_context.h"#include "vbs_lex.h"#include "vbs_grammar.tab.h"#ifndef Statementtypedef struct Statement_struct *Statement;#endif#ifndef Expressiontypedef struct Expression_struct *Expression;#endif#ifndef CaseListtypedef struct CaseList_struct *CaseList;#endif#include "ast.h"extern "C" void execute(Statement s, Cvbs_context& c);extern "C" string evaluate(Expression e, Cvbs_context& c);int yylex(YYSTYPE* str, YYLTYPE * yyloc, Cvbs_context* pcnt);int yyerror(YYLTYPE *locp,Cvbs_context* pcnt,const char* msg);%} %union { char* szVal; struct Statement_struct* stmt; struct Expression_struct* exp; struct CaseList_struct* caselist;}%start ROOT%token EQ%token NE%token LT%token LE%token GT%token GE%token XOR%token OR%token PLUS%token MINUS%token MULT%token DIVIDE%token RPAREN%token LPAREN%token ASSIGN%token SEMICOLON%token IF%token THEN%token ELSE%token ELSEIF%token ENDIF%token WHILE%token WEND%token LOOP%token EXIT%token UNTIL%token FOR%token TO%token NEXT%token STEP%token DO%token END%token SELECT%token CASE%token PRINT%token DIM%token TYPE%token SUB%token <szVal> SUB_BODY%token <szVal> FUNC_BODY%token FUNCTION%token ENDFUNC%token AS%token COMMA%token BYVAL%token BYREF%token PRIVATE%token PUBLIC%token EXITSUB%token EXITFUNC%token DEFAULT%token <szVal> NUMBER%token <szVal> STRING%token <szVal> NAME%token <szVal> NAME_SUB%token <szVal> TRUE%token <szVal> FALSE%token COLON%token CALL%token EVAL%token AND%token AMD%token NOT%token LBOUND%token UBOUND%token CLNG%token DATE%token GETSTRING%token CSTR%token INSTR%token INSTRREV%token JOIN%token LEN%token RANDOMIZE %token RND%token TIME%token YEAR%token MONTH%token DAY%token WEEKDAY%token HOUR%token MINUTE%token SECOND%type <stmt> ROOT stmtseq statement declare declare_var declare_sub declare_func elseif_seq%type <exp> expression expr2 expr3 expr4 designator arg func%type <caselist> case_seq arglist argref_list subscript upper //%destructor { free($$);} NUMBER STRING TRUE FALSE%%ROOT: stmtseq { execute($1,*cnt); } ;statement: designator EQ expression { $$ = assignment($1, $3,cnt);} | PRINT expression { $$ = print($2,cnt); } | IF expression THEN stmtseq ELSE stmtseq END IF { $$ = ifstmt($2, $4, $6,cnt); }| IF expression THEN stmtseq END IF { $$ = ifstmt($2, $4, empty(cnt),cnt); }| IF expression THEN stmtseq elseif_seq END IF { $$ = ifstmt($2,$4,$5,cnt);}| SELECT CASE expression case_seq CASE ELSE stmtseq END SELECT {$$ = select_case($3,$4,$7,cnt);}| SELECT CASE expression case_seq END SELECT {$$ = select_case($3,$4,empty(cnt),cnt);} | WHILE expression stmtseq WEND { $$ = whilestmt($2, $3,cnt); }| DO WHILE expression stmtseq LOOP { $$ = dowhileloop($3,$4,cnt);}| DO UNTIL expression stmtseq LOOP { $$ = dountilloop($3,$4,cnt);}| DO stmtseq LOOP WHILE expression { $$ = doloopwhile($2,$5,cnt);}| DO stmtseq LOOP UNTIL expression { $$ = doloopuntil($2,$5,cnt);}| EXIT DO { $$ = exitdo(cnt); }| EXIT FOR { $$ = exitfor(cnt);}| FOR NAME EQ expression TO expression STEP expression stmtseq NEXT { $$=fornext(name($2,cnt),$4,$6,$8,$9,cnt);}| FOR NAME EQ expression TO expression stmtseq NEXT { $$=fornext(name($2,cnt),$4,$6,value("#1",cnt),$7,cnt);}| declare | EXIT SUB { $$ = exitsub(cnt); }| EXIT FUNCTION { $$ = exitsub(cnt); }| CALL NAME_SUB LPAREN argref_list RPAREN { $$ = callsub($2,$4,cnt);}| CALL NAME_SUB { $$ = callsub($2,null(cnt),cnt);}| NAME_SUB argref_list { $$ = callsub($1,$2,cnt);}| EVAL expression { $$ = eval($2,cnt);}| NAME_SUB { $$ = callsub($1,null(cnt),cnt);}| RANDOMIZE LPAREN expression RPAREN { $$ = randomize($3,cnt);}| RANDOMIZE { $$ = randomize0(cnt);} ;stmtseq: stmtseq statement { $$ = seq($1, $2,cnt); }| stmtseq COLON statement {$$ = seq($1,$3,cnt);}| statement { $$ = $1; };case_seq: CASE expression stmtseq {$$ = case_node($2,$3,null(cnt),cnt);}| case_seq CASE expression stmtseq {$$ = case_node($3,$4,$1,cnt);};elseif_seq: ELSEIF expression THEN stmtseq {$$ = ifstmt($2,$4,empty(cnt),cnt);}| elseif_seq ELSEIF expression THEN stmtseq {$$ = seq($1,ifstmt($3,$5,empty(cnt),cnt),cnt);}| elseif_seq ELSEIF expression THEN stmtseq ELSE stmtseq {$$ = seq($1,ifstmt($3,$5,$7,cnt),cnt);};argref_list: expression {$$=argreflist($1,null(cnt),cnt);}| argref_list COMMA expression {$$=argreflist($3,$1,cnt); }expression: expr2 { $$ = $1; } | expr2 EQ expr2 { $$ = eq($1,$3,cnt); }| expr2 NE expr2 { $$ = ne($1,$3,cnt); }| expr2 LT expr2 { $$ = lt($1,$3,cnt); }| expr2 LE expr2 { $$ = le($1,$3,cnt); }| expr2 GT expr2 { $$ = gt($1,$3,cnt); }| expr2 GE expr2 { $$ = ge($1,$3,cnt); }| expression AND expression { $$ = vband($1,$3,cnt);}| expression OR expression { $$ = vbor($1,$3,cnt);}| expression XOR expression { $$ = vbxor($1,$3,cnt);};expr2: expr3 { $$ = $1; }| expr2 PLUS expr3 { $$ = splus($1,$3,cnt); }| expr2 MINUS expr3 { $$ = sminus($1,$3,cnt); }| expr2 AMD expr3 { $$ = amd($1,$3,cnt);};expr3: expr4 { $$ = $1; }| expr3 MULT expr4 { $$ = mult($1, $3,cnt); }| expr3 DIVIDE expr4 { $$ = divide ($1, $3,cnt); };expr4: PLUS expr4 { $$ = $2; }| MINUS expr4 { $$ = neg($2,cnt); }| NOT expr4 { $$ = vbnot($2,cnt);}| LPAREN expression RPAREN { $$ = $2; }| NUMBER { $$ = value($1,cnt)}| STRING { $$ = value($1,cnt)}| TRUE { $$ = value($1,cnt)}| FALSE { $$ = value($1,cnt)}| designator { $$ = $1; }| func { $$ = $1;};func: LBOUND LPAREN NAME RPAREN { $$ = lbound($3,1,cnt);}| UBOUND LPAREN NAME RPAREN { $$ = ubound($3,1,cnt);}| CLNG LPAREN expression RPAREN { $$ = clng($3,cnt);}| DATE { $$ = date(cnt); }| GETSTRING LPAREN expression COMMA expression COMMA expression RPAREN {$$ = getstring($3,$5,$7,cnt);}| INSTR LPAREN expression COMMA expression RPAREN { $$ = instr(value("#0",cnt),$3,$5,value("#0",cnt),cnt);}| INSTR LPAREN expression COMMA expression COMMA expression RPAREN {$$ = instr($3,$5,$7,value("#0",cnt),cnt);}| INSTR LPAREN expression COMMA expression COMMA expression COMMA expression RPAREN {$$ = instr($3,$5,$7,$9,cnt);}| CSTR LPAREN expression RPAREN { $$ = cstr($3,cnt);}| LEN LPAREN expression RPAREN { $$ = len($3,cnt);}| RND LPAREN expression RPAREN { $$ = rnd($3,cnt);}| RND { $$ = rnd0(cnt); } | TIME { $$ = vbtime(cnt); }| YEAR LPAREN expression RPAREN { $$ = vyear($3,cnt);}| MONTH LPAREN expression RPAREN { $$ = vmonth($3,cnt);}| DAY LPAREN expression RPAREN { $$ = vday($3,cnt);}| WEEKDAY LPAREN expression RPAREN {$$ = vweekday($3,cnt);}| HOUR LPAREN expression RPAREN { $$ = vhour($3,cnt);}| MINUTE LPAREN expression RPAREN {$$ = vminute($3,cnt);}| SECOND LPAREN expression RPAREN {$$ = vsecond($3,cnt);};designator: NAME LPAREN argref_list RPAREN {$$ = name_array($1,$3,cnt);}| NAME { $$ = name($1,cnt); };declare: declare_var | declare_sub | declare_func ;declare_var: DIM NAME {$$ = decl($2,cnt); } | DIM NAME subscript {$$ = declarray($2,$3,cnt); }| DIM NAME AS TYPE {$$ = decl($2,cnt); }| DIM NAME subscript AS TYPE {$$ = declarray($2,$3,cnt); }| PRIVATE NAME {$$ = decl($2,cnt); }| PRIVATE NAME subscript {$$ = declarray($2,$3,cnt); }| PRIVATE NAME AS TYPE {$$ = decl($2,cnt); }| PRIVATE NAME subscript AS TYPE {$$ = declarray($2,$3,cnt); }| PUBLIC NAME {$$ = decl($2,cnt); }| PUBLIC NAME subscript {$$ = declarray($2,$3,cnt); }| PUBLIC NAME AS TYPE {$$ = decl($2,cnt); }| PUBLIC NAME subscript AS TYPE {$$ = declarray($2,$3,cnt); }| declare_var COMMA NAME {$$ = decl($3,cnt); }| declare_var COMMA NAME subscript {$$ = declarray($3,$4,cnt); }| declare_var COMMA NAME AS TYPE {$$ = decl($3,cnt); }| declare_var COMMA NAME subscript AS TYPE {$$ = declarray($3,$4,cnt); };declare_sub: SUB NAME LPAREN arglist RPAREN SUB_BODY {$$ = declsub($2,$4,$6,cnt);cnt->save_func($2);}| SUB NAME LPAREN RPAREN SUB_BODY {$$ = declsub($2,null(cnt),$5,cnt);cnt->save_func($2);}| PUBLIC SUB NAME LPAREN arglist RPAREN SUB_BODY {$$ = declsub($3,$5,$7,cnt);cnt->save_func($3);}| PUBLIC SUB NAME LPAREN RPAREN SUB_BODY {$$ = declsub($3,null(cnt),$6,cnt);cnt->save_func($3);}| PUBLIC DEFAULT SUB NAME LPAREN arglist RPAREN SUB_BODY {$$ = declsub($4,$6,$8,cnt);cnt->save_func($4);}| PUBLIC DEFAULT SUB NAME LPAREN RPAREN SUB_BODY {$$ = declsub($4,null(cnt),$7,cnt);cnt->save_func($4);}| PRIVATE SUB NAME LPAREN arglist RPAREN SUB_BODY {$$ = declsub($3,$5,$7,cnt);cnt->save_func($3);}| PRIVATE SUB NAME LPAREN RPAREN SUB_BODY {$$ = declsub($3,null(cnt),$6,cnt);cnt->save_func($3);};declare_func: FUNCTION NAME LPAREN arglist RPAREN FUNC_BODY {$$ = declsub($2,$4,$6,cnt);cnt->save_func($2);} | FUNCTION NAME LPAREN RPAREN FUNC_BODY {$$ = declsub($2,null(cnt),$5,cnt);cnt->save_func($2);}| PUBLIC FUNCTION NAME LPAREN arglist RPAREN FUNC_BODY {$$ = declsub($3,$5,$7,cnt);cnt->save_func($3);}| PUBLIC FUNCTION NAME LPAREN RPAREN FUNC_BODY {$$ = declsub($3,null(cnt),$6,cnt);cnt->save_func($3);}| PUBLIC DEFAULT FUNCTION NAME LPAREN arglist RPAREN FUNC_BODY {$$ = declsub($4,$6,$8,cnt);cnt->save_func($4);}| PUBLIC DEFAULT FUNCTION NAME LPAREN RPAREN FUNC_BODY {$$ = declsub($4,null(cnt),$7,cnt);cnt->save_func($4);}| PRIVATE FUNCTION NAME LPAREN arglist RPAREN FUNC_BODY {$$ = declsub($3,$5,$7,cnt);cnt->save_func($3);}| PRIVATE FUNCTION NAME LPAREN RPAREN FUNC_BODY {$$ = declsub($3,null(cnt),$6,cnt);cnt->save_func($3);};arg: NAME {$$=name($1,cnt);}| BYVAL NAME {$$=name($2,cnt);}| BYREF NAME {$$=name((string($2)+string("*")).c_str(),cnt);};arglist: arg {$$ = arglist($1,null(cnt),cnt); }| arglist COMMA arg {$$ = arglist($3,$1,cnt); }; subscript: LPAREN upper RPAREN {$$ = $2;};upper: NUMBER { $$=subs(atoi($1+1),null(cnt),cnt);}| upper COMMA NUMBER { $$=subs(atoi($3+1),$1,cnt);};%%int yylex(YYSTYPE* str, YYLTYPE * yyloc, Cvbs_context* pcnt){ pcnt->strValue.clear(); pcnt->szValue = NULL; register int n=vbslex(pcnt->get_scanner()); if (pcnt->szValue || n == TRUE || n == FALSE) { string sTmp; switch(n) { case NUMBER: sTmp = "#";//number prefix sTmp += pcnt->szValue; pcnt->szValue = sTmp.c_str(); break; case STRING: sTmp = "$";//string prefix sTmp += pcnt->szValue; pcnt->szValue = sTmp.c_str(); break; case TRUE: sTmp = "True"; pcnt->szValue = sTmp.c_str(); break; case FALSE: sTmp = "False"; pcnt->szValue = sTmp.c_str(); break; default: //sTmp = pcnt->strValue; break; } //str->szVal = strdup(pcnt->szValue); int len = strlen(pcnt->szValue)+1; str->szVal = (char*)pcnt->Alloc(len); memcpy(str->szVal,pcnt->szValue,len); pcnt->strValue.clear(); } yyloc->first_line=yyloc->last_line = vbsget_lineno(pcnt->get_scanner()); yyloc->first_column=pcnt->nlastCol - vbsget_leng(pcnt->get_scanner()); yyloc->last_column=pcnt->nlastCol - 1; return n;} int yyerror(YYLTYPE *locp,Cvbs_context* pcnt,const char* msg){ if (!locp) TRACE(0,"VBS ERROR:null locp"); TRACE(0,"PARSE ERROR on line %d:%d-%d error:%s", locp->first_line,locp->first_column,locp->last_column,msg);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -