X/* X * Bawk C actions parser X */ X#include X#include "bawk.h" X Xstatic char operator_strength[] = { X0, /* 0 */ X0, /* CHAR */ X0, /* BOL */ X0, /* EOL */ X0, /* ANY */ X0, /* CLASS */ X0, /* NCLASS */ X0, /* STAR */ X0, /* PLUS */ X0, /* MINUS */ X0, /* ALPHA */ X0, /* DIGIT */ X0, /* NALPHA */ X0, /* PUNCT */ X0, /* RANGE */ X0, /* ENDPAT */ X0, /* T_STRING */ X0, /* T_DOLLAR */ X0, /* T_REGEXP */ X0, /* T_REGEXP_ARG */ X0, /* T_CONSTANT */ X0, /* T_VARIABLE */ X0, /* T_FUNCTION */ X0, /* T_SEMICOLON */ X0, /* T_EOF */ X0, /* T_LBRACE */ X0, /* T_RBRACE */ X0, /* T_LPAREN */ X0, /* T_RPAREN */ X0, /* T_LBRACKET */ X0, /* T_RBRACKET */ X0, /* T_COMMA */ X1, /* T_ASSIGN */ X0, /* T_STAR */ X11, /* T_MUL */ X11, /* T_DIV */ X11, /* T_MOD */ X10, /* T_ADD */ X0, /* T_UMINUS */ X10, /* T_SUB */ X9, /* T_SHL */ X9, /* T_SHR */ X8, /* T_LT */ X8, /* T_LE */ X8, /* T_GT */ X8, /* T_GE */ X7, /* T_EQ */ X7, /* T_NE */ X0, /* T_NOT */ X0, /* T_ADDROF */ X6, /* T_AND */ X5, /* T_XOR */ X4, /* T_OR */ X0, /* T_LNOT */ X3, /* T_LAND */ X2, /* T_LOR */ X0, /* T_INCR */ X0, /* T_DECR */ X0, /* T_POSTINCR */ X0, /* T_POSTDECR */ X0, /* T_IF */ X0, /* T_ELSE */ X0, /* T_WHILE */ X0, /* T_BREAK */ X0, /* T_CHAR */ X0, /* T_INT */ X0, /* T_BEGIN */ X0, /* T_END */ X0, /* T_NF */ X0, /* T_NR */ X0, /* T_FS */ X0, /* T_RS */ X0, /* T_FILENAME */ X0, /* T_STATEMENT */ X0, /* T_DECLARE */ X0 /* T_ARRAY_DECLARE */ X}; X XEXPR_NODE *stmt_parse() X{ X /* X * Parse a statement. X */ X register EXPR_NODE *root = NULL, *end_pointer, *tmp; X X DBUG_ENTER("stmt_parse"); X switch ( Token ) X { X case T_EOF: X break; X case T_CHAR: X case T_INT: X root = declist_parse(); X break; X case T_LBRACE: X /* X * parse a compound statement X */ X getoken(); X while ( Token != T_RBRACE ) X { X tmp = get_expr_node((char) T_STATEMENT); X if(!root) { X root = end_pointer = tmp; X } else { X end_pointer->right = tmp; X end_pointer = tmp; X } X end_pointer->left = stmt_parse(); X } X if ( Token==T_RBRACE ) X getoken(); X break; X case T_IF: X /* X * parse an "if-else" statement X */ X if ( getoken() != T_LPAREN ) X syntaxerror(); X getoken(); X root = get_expr_node((char) T_IF); X root->left = end_pointer = get_expr_node((char) T_IF); X end_pointer->left = expr_parse(); X if ( Token!=T_RPAREN ) X syntaxerror(); X getoken(); X end_pointer->right = stmt_parse(); X if ( Token==T_ELSE ) X { X getoken(); X root->right = stmt_parse(); X } X break; X case T_WHILE: X /* X * parse a "while" statement X */ X root = get_expr_node((char) T_WHILE); X if ( getoken() != T_LPAREN ) X syntaxerror(); X X getoken(); X root->left = expr_parse(); X if ( Token!=T_RPAREN ) X syntaxerror(); X X getoken(); X root->right = stmt_parse(); X break; X case T_BREAK: X /* X * parse a "break" statement X */ X root = get_expr_node((char) T_BREAK); X getoken(); X break; X case T_SEMICOLON: X break; X default: X root = expr_parse(); X } X X if ( Token==T_SEMICOLON ) X getoken(); X DBUG_RETURN(root); X} X XEXPR_NODE *expr_parse() X{ X register EXPR_NODE *root, *tmp; X register char strength; X X DBUG_ENTER("expr_parse"); X strength = operator_strength[T_ASSIGN]; X root = expr_left_to_right_parse(strength); X if(strength == operator_strength[Token]) X { X /* assignments are grouped right to left */ X tmp = get_expr_node(Token); X tmp->left = root; X root = tmp; X getoken(); X root->right = expr_parse(); X } X DBUG_RETURN(root); X} X XEXPR_NODE *expr_left_to_right_parse(parent_strength) Xregister char parent_strength; X{ X register EXPR_NODE *root, *tmp; X register char strength; X X DBUG_ENTER("expr_left_to_right_parse"); X root = primary_parse(); X if(parent_strength < (strength = operator_strength[Token])) X { X while(strength == operator_strength[Token]) X { X tmp = get_expr_node(Token); X tmp->left = root; X root = tmp; X getoken(); X root->right = expr_left_to_right_parse(strength); X } X } X DBUG_RETURN(root); X} X XEXPR_NODE *primary_parse() X{ X register EXPR_NODE *root = NULL, *end_pointer, *tmp; X register int lpar; X X DBUG_ENTER("primary_parse"); X switch ( Token ) X { X case T_LPAREN: X /* X * it's a parenthesized expression X */ X getoken(); X root = expr_parse(); X if ( Token!=T_RPAREN ) X error( "missing ')'", ACT_ERROR ); X getoken(); X break; X case T_LNOT: X case T_NOT: X case T_INCR: X case T_DECR: X case T_DOLLAR: X root = get_expr_node(Token); X getoken(); X root->left = primary_parse(); X break; X case T_SUB: X root = get_expr_node((char) T_UMINUS); X getoken(); X root->left = primary_parse(); X break; X case T_MUL: X root = get_expr_node((char) T_STAR); X getoken(); X root->left = primary_parse(); X break; X case T_AND: X root = get_expr_node((char) T_ADDROF); X getoken(); X root->left = primary_parse(); X break; X case T_ADD: X getoken(); X root = primary_parse(); X break; X case T_CONSTANT: X root = get_expr_node(Token); X root->left = (EXPR_NODE *) getmemory(sizeof(DATUM)); X ((DATUM *) (root->left))->ival = Value.ival; X getoken(); X break; X case T_FUNCTION: X root = get_expr_node(Token); X root->left = (EXPR_NODE *) getmemory(sizeof(DATUM)); X ((DATUM *) (root->left))->ival = Value.ival; X getoken(); X if ( Token==T_LPAREN ) X { X lpar = 1; X getoken(); X } X else X lpar = 0; X /* X * Parse arguments into a list of expressions. X */ X if ( Token!=T_RPAREN && Token!=T_EOF ) X { X for ( ;; ) X { X tmp = get_expr_node((char) T_FUNCTION); X if(!root->right) { X root->right = end_pointer = tmp; X } else { X end_pointer->right = tmp; X end_pointer = tmp; X } X end_pointer->left = expr_parse(); X if((tmp = end_pointer->left) && X (tmp->operator == T_REGEXP)) X tmp->operator = T_REGEXP_ARG; X if ( Token==T_COMMA ) X getoken(); X else X break; X } X } X if ( lpar ) X if( Token!=T_RPAREN ) X error( "missing ')'", ACT_ERROR ); X else X getoken(); X break; X case T_REGEXP: X case T_STRING: X root = get_expr_node(Token); X root->left = (EXPR_NODE *) getmemory(strlen(Value.dptr) + 1); X strcpy((char *) root->left, Value.dptr); X getoken(); X break; X case T_NF: X case T_NR: X case T_FS: X case T_RS: X case T_FILENAME: X case T_BEGIN: X case T_END: X root = get_expr_node(Token); X getoken(); X break; X case T_VARIABLE: X root = get_expr_node(Token); X root->left = (EXPR_NODE *) Value.dptr; X getoken(); X break; X case T_EOF: X break; X default: X syntaxerror(); X } X /* X * a "[" means it's an array reference X */ X if ( Token==T_LBRACKET ) X { X tmp = get_expr_node(Token); X tmp->left = root; X root = tmp; X getoken(); X root->right = expr_parse(); X if ( Token!=T_RBRACKET ) X error( "missing ']'", ACT_ERROR ); X getoken(); X } X X if ( Token==T_INCR || Token==T_DECR ) X { X tmp = get_expr_node((char) X ((Token==T_INCR) ? T_POSTINCR : T_POSTDECR)); X tmp->left = root; X root = tmp; X } X DBUG_RETURN(root); X} X Xvoid syntaxerror() X{ X DBUG_ENTER("syntaxerror"); X error( "syntax error", ACT_ERROR ); X DBUG_VOID_RETURN; X}