/* * OpenPBS (Portable Batch System) v2.3 Software License * * Copyright (c) 1999-2000 Veridian Information Solutions, Inc. * All rights reserved. * * --------------------------------------------------------------------------- * For a license to use or redistribute the OpenPBS software under conditions * other than those described below, or to purchase support for this software, * please contact Veridian Systems, PBS Products Department ("Licensor") at: * * www.OpenPBS.org +1 650 967-4675 sales@OpenPBS.org * 877 902-4PBS (US toll-free) * --------------------------------------------------------------------------- * * This license covers use of the OpenPBS v2.3 software (the "Software") at * your site or location, and, for certain users, redistribution of the * Software to other sites and locations. Use and redistribution of * OpenPBS v2.3 in source and binary forms, with or without modification, * are permitted provided that all of the following conditions are met. * After December 31, 2001, only conditions 3-6 must be met: * * 1. Commercial and/or non-commercial use of the Software is permitted * provided a current software registration is on file at www.OpenPBS.org. * If use of this software contributes to a publication, product, or * service, proper attribution must be given; see www.OpenPBS.org/credit.html * * 2. Redistribution in any form is only permitted for non-commercial, * non-profit purposes. There can be no charge for the Software or any * software incorporating the Software. Further, there can be no * expectation of revenue generated as a consequence of redistributing * the Software. * * 3. Any Redistribution of source code must retain the above copyright notice * and the acknowledgment contained in paragraph 6, this list of conditions * and the disclaimer contained in paragraph 7. * * 4. Any Redistribution in binary form must reproduce the above copyright * notice and the acknowledgment contained in paragraph 6, this list of * conditions and the disclaimer contained in paragraph 7 in the * documentation and/or other materials provided with the distribution. * * 5. Redistributions in any form must be accompanied by information on how to * obtain complete source code for the OpenPBS software and any * modifications and/or additions to the OpenPBS software. The source code * must either be included in the distribution or be available for no more * than the cost of distribution plus a nominal fee, and all modifications * and additions to the Software must be freely redistributable by any party * (including Licensor) without restriction. * * 6. All advertising materials mentioning features or use of the Software must * display the following acknowledgment: * * "This product includes software developed by NASA Ames Research Center, * Lawrence Livermore National Laboratory, and Veridian Information * Solutions, Inc. * Visit www.OpenPBS.org for OpenPBS software support, * products, and information." * * 7. DISCLAIMER OF WARRANTY * * THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT * ARE EXPRESSLY DISCLAIMED. * * IN NO EVENT SHALL VERIDIAN CORPORATION, ITS AFFILIATED COMPANIES, OR THE * U.S. GOVERNMENT OR ANY OF ITS AGENCIES BE LIABLE FOR ANY DIRECT OR INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * This license will be governed by the laws of the Commonwealth of Virginia, * without reference to its choice of law rules. */ /************************************************************* * myname Parser.b * created 7/2/1996 * updated 12/20/1996 * works 12/20/1996 * * designed rrs/1996 *************************************************************/ /*********************************************************** * * OPERATION OVERVIEW * * The Bison will generate a Parser that parses input * in NASL language. * The Scanner which resides in the other files is generated by Flex * from the source file Lexer.fl. * ************************************************************/ /*********************************************************** * SOFTWARE ENGINEERING METHODS * The Compiler was designed as a collection of entities * which communicate across well defined intefaces similar * objects in C++. * This approach allows independence in design, * implementation, and testing. * each "object" in addition contains support routines for * self-diagnosis. ***********************************************************/ /* Libraries, Types, tokens, precedences */ %{ #include #include #include #include #include #include #include "Parser.h" #include "Semantic.h" #include "CodeGen.h" #include "af.h" Np np; extern int linenum; extern char linebuf[]; extern jmp_buf begin; extern int sizeStrcmp(); extern int sizeRangeStrcmp(); extern int strToInt(); extern double strToFloat(); int intval; int intval2; int inLoop = 0; int inSwitch = 0; char bufstr[10]; char bufstr2[300]; %} %union { struct MYTOK mytok; } /* tokens */ /*main*/ %token MAIN /*data types simple*/ %token VOID %token INT %token FLOAT %token DAYOFWEEK %token DATETIME %token STRING %token FUN %token SIZE /*data types complex*/ %token SERVER %token QUE %token JOB %token CNODE /*data types qualifiers*/ %token SET %token RANGE /*constants*/ %token INTCONST %token FLOATCONST %token DAYOFWEEKCONST %token STRINGCONST %token SIZECONST %token SERVERCONST %token JOBCONST %token QUECONST %token CNODECONST %token SETSERVERCONST %token SETJOBCONST %token SETQUECONST %token SETCNODECONST /*instruction keywords*/ %token WHILE %token IF %token ELSE %token RETURN %token PRINT %token FOR %token FOREACH %token IN %token SWITCH %token CASE %token BREAK %token CONTINUE %token EXIT /*compare etc*/ %token EQ %token NEQ %token LT %token LE %token GT %token GE %token MIN %token MAX /*logical*/ %token AND %token OR /*misc*/ %token '(' %token ')' %token ';' %token ':' %token '|' %token ',' %token '{' %token '}' %token '@' %token POSTOP %token DEFAULT /*ident*/ %token IDENT /* * Types of symbols */ /*types*/ /*main*/ %type MAIN /*data types simple*/ %type VOID %type INT %type FLOAT %type DAYOFWEEK %type DATETIME %type STRING %type FUN %type SIZE /*data types complex*/ %type SERVER %type QUE %type JOB %type CNODE /*data types qualifiers*/ %type SET %type RANGE /*constants*/ %type INTCONST %type FLOATCONST %type DAYOFWEEKCONST %type STRINGCONST %type SIZECONST %type SERVERCONST %type JOBCONST %type QUECONST %type CNODECONST %type SETSERVERCONST %type SETJOBCONST %type SETQUECONST %type SETCNODECONST /*instruction keywords*/ %type WHILE %type IF %type ELSE %type RETURN %type PRINT %type FOR %type FOREACH %type IN %type SWITCH %type CASE %type BREAK %type CONTINUE %type EXIT /*compare etc*/ %type EQ %type NEQ %type LT %type LE %type GT %type GE %type MIN %type MAX /*logical*/ %type AND %type OR /*vars*/ %type var /*ident*/ %type IDENT /* misc */ %type '{' %type '}' %type '(' %type ')' %type ';' %type ':' %type '|' %type '@' %type ',' %type POSTOP %type DEFAULT %type expr %type exprTerms %type consts %type intConst %type floatConst %type dataTypes %type dataTypesSimple %type dataTypesComplex %type dataTypesSet %type dataTypesRange %type funCall %type dayofweekConst %type datetimeConst %type stringConst %type sizeConst %type serverConst %type queConst %type jobConst %type cnodeConst %type setServerConst %type setQueConst %type setJobConst %type setCnodeConst %type cprOp %type constRange %type intConstRange %type floatConstRange %type dayofweekConstRange %type datetimeConstRange %type sizeConstRange %type arg %type lb %type rb %type comma %type colon %type pipe %type at /* precedences */ %right '=' %left OR %left AND %left EQ NEQ %left LT LE GT GE %left '+' '-' %left '*' '/' '%' %right NOT POSTOP UPLUS UMINUS /* unary - */ %% /* Rules */ prog: defs1 globAssign { CodeGenBuffSave("}"); CodeGenBuffSave("\n"); CodeGenBuffEmit(); } mainProg { ParserCondPrint("prog"); ParserCondPrint("\n***WHOLE PROGRAM PARSED OK***\n"); } ; defs1: /* lambda */ { ParserCondPrint("defs1"); ParserCondPrint("\n***DEFS1 PARSED OK***\n"); } | defs1 defFun { ParserCondPrint("defs1"); } | defs1 def { ParserCondPrint("defs1"); } ; globAssign: /* lambda */ { ParserCondPrint("globAssign"); CodeGenBuffSave("void sched_init()"); CodeGenBuffSave("\n"); CodeGenBuffSave("{"); CodeGenBuffSave("\n"); } | globAssign statAssign mainProg: progHead blockWithDefs { ParserCondPrint("mainProg"); ParserPutDF(1); ParserCondPrint("\n***MAIN PROGRAM PARSED OK***\n"); ParserPutDF(0); } ; progHead: MAIN { ParserVarScopeIncr(); CodeGenBuffSave("void sched_main"); } lb rb { ParserCondPrint("progHead"); $1.type = VOIDTYPE; np = NodeNew( (char *) $1.lexeme, $1.type, $1.line, ParserLevelGet(), YES); /* NodePrint(np); */ SymTabInsertFront(np); ParserCurrFunPtrPut(np); } ; blockWithDefs: lcb defs { ParserCondPrint("blockWithDefs"); } stats rcb { ParserCondPrint("blockWithDefs"); } ; block: lcb stats rcb { ParserCondPrint("block"); } ; defs: /*lambda*/ { ParserCondPrint("defs"); } | defs def { ParserCondPrint("defs"); } ; def: defSimple { ParserCondPrint("def"); } | defComplex { ParserCondPrint("def"); } | defSet { ParserCondPrint("def"); } | defRange { ParserCondPrint("def"); } ; /*all data types */ dataTypes: dataTypesSimple { ParserCondPrint("dataTypes"); } | dataTypesComplex { ParserCondPrint("dataTypes"); } | dataTypesSet { ParserCondPrint("dataTypes"); } | dataTypesRange { ParserCondPrint("dataTypes"); } ; /*this will be done more elgantly; -- see statPrint*/ /*data types simple*/ dataTypesSimple: INT { ParserCondPrint("dataTypesSimple"); $$.type = INTTYPE; /*semantic type*/ if( ParserLevelGet() == 0 ) CodeGenBuffSave("static "); CodeGenBuffSave("int "); } | VOID { ParserCondPrint("dataTypesSimple"); $$.type = VOIDTYPE; if( ParserLevelGet() == 0 ) CodeGenBuffSave("static "); CodeGenBuffSave("void "); } | FLOAT { ParserCondPrint("dataTypesSimple"); $$.type = FLOATTYPE; /*semantic type*/ if( ParserLevelGet() == 0 ) CodeGenBuffSave("static "); CodeGenBuffSave("double "); } | DAYOFWEEK { ParserCondPrint("dataTypesSimple"); $$.type = DAYOFWEEKTYPE; /*semantic type*/ if( ParserLevelGet() == 0 ) CodeGenBuffSave("static "); CodeGenBuffSave("Dayofweek "); } | DATETIME { ParserCondPrint("dataTypesSimple"); $$.type = DATETIMETYPE; /*semantic type*/ if( ParserLevelGet() == 0 ) CodeGenBuffSave("static "); CodeGenBuffSave("DateTime "); } | STRING { ParserCondPrint("dataTypesSimple"); $$.type = STRINGTYPE; /*semantic type*/ if( ParserLevelGet() == 0 ) CodeGenBuffSave("static "); CodeGenBuffSave("char *"); } | SIZE { ParserCondPrint("dataTypesSimple"); $$.type = SIZETYPE; /*semantic type*/ if( ParserLevelGet() == 0 ) CodeGenBuffSave("static "); CodeGenBuffSave("Size "); } ; /*def data types simple*/ defSimple: dataTypesSimple IDENT { $2.type = $1.type; if( $1.type == VOIDTYPE ) SemanticErr(27); CodeGenBuffSave((char *)$2.lexeme); if( $2.type == STRINGTYPE ) { CodeGenBuffSave(" = NULLSTR"); } } sc { ParserCondPrint("defSimple"); if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, ParserLevelGet() ) != NULL ) { SemanticErr(7); } np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), NO); /* NodePrint(np); */ SymTabInsertFront(np); } ; /*data types Complex*/ dataTypesComplex: SERVER { ParserCondPrint("dataTypesComplex"); $$.type = SERVERTYPE; if( ParserLevelGet() == 0 ) CodeGenBuffSave("static "); CodeGenBuffSave("Server *"); } | QUE { ParserCondPrint("dataTypesComplex"); $$.type = QUETYPE; if( ParserLevelGet() == 0 ) CodeGenBuffSave("static "); CodeGenBuffSave("Que *"); } | JOB { ParserCondPrint("dataTypesComplex"); $$.type = JOBTYPE; if( ParserLevelGet() == 0 ) CodeGenBuffSave("static "); CodeGenBuffSave("Job *"); } | CNODE { ParserCondPrint("dataTypesComplex"); $$.type = CNODETYPE; if( ParserLevelGet() == 0 ) CodeGenBuffSave("static "); CodeGenBuffSave("CNode *"); } ; /*def data types Complex*/ defComplex: dataTypesComplex IDENT { $2.type = $1.type; CodeGenBuffSave((char *)$2.lexeme); switch($2.type) { case SERVERTYPE: CodeGenBuffSave(" = NOSERVER"); break; case QUETYPE: CodeGenBuffSave(" = NOQUE"); break; case JOBTYPE: CodeGenBuffSave(" = NOJOB"); break; case CNODETYPE: CodeGenBuffSave(" = NOCNODE"); break; } } sc { ParserCondPrint("defComplex"); if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, ParserLevelGet() ) != NULL ) { SemanticErr(7); } np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), NO); /* NodePrint(np); */ SymTabInsertFront(np); } ; dataTypesSet: SET SERVER { ParserCondPrint("dataTypesSet"); $$.type = SERVERSETTYPE; if( ParserLevelGet() == 0 ) CodeGenBuffSave("static "); CodeGenBuffSave("SetServer *"); } | SET QUE { ParserCondPrint("dataTypesSet"); $$.type = QUESETTYPE; if( ParserLevelGet() == 0 ) CodeGenBuffSave("static "); CodeGenBuffSave("SetQue *"); } | SET JOB { ParserCondPrint("dataTypesSet"); $$.type = JOBSETTYPE; if( ParserLevelGet() == 0 ) CodeGenBuffSave("static "); CodeGenBuffSave("struct SetJobElement *"); } | SET CNODE { ParserCondPrint("dataTypesSet"); $$.type = CNODESETTYPE; if( ParserLevelGet() == 0 ) CodeGenBuffSave("static "); CodeGenBuffSave("SetCNode *"); } ; /*def data types Set*/ defSet: dataTypesSet IDENT { $2.type = $1.type; CodeGenBuffSave((char *)$2.lexeme); switch($2.type) { case SERVERSETTYPE: CodeGenBuffSave(" = EMPTYSETSERVER"); break; case QUESETTYPE: CodeGenBuffSave(" = EMPTYSETQUE"); break; case JOBSETTYPE: CodeGenBuffSave(" = EMPTYSETJOB"); break; case CNODESETTYPE: CodeGenBuffSave(" = EMPTYSETCNODE"); break; } } sc { ParserCondPrint("defSet"); if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, ParserLevelGet() ) != NULL ) { SemanticErr(7); } np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), NO); /* NodePrint(np); */ SymTabInsertFront(np); } ; /*data types Range*/ dataTypesRange: RANGE INT { ParserCondPrint("dataTypesRange"); $$.type = INTRANGETYPE; if( ParserLevelGet() == 0 ) CodeGenBuffSave("static "); CodeGenBuffSave("IntRange "); } | RANGE FLOAT { ParserCondPrint("dataTypesRange"); $$.type = FLOATRANGETYPE; if( ParserLevelGet() == 0 ) CodeGenBuffSave("static "); CodeGenBuffSave("FloatRange "); } | RANGE DAYOFWEEK { ParserCondPrint("dataTypesRange"); $$.type = DAYOFWEEKRANGETYPE; if( ParserLevelGet() == 0 ) CodeGenBuffSave("static "); CodeGenBuffSave("DayofweekRange "); } | RANGE DATETIME { ParserCondPrint("dataTypesRange"); $$.type = DATETIMERANGETYPE; if( ParserLevelGet() == 0 ) CodeGenBuffSave("static "); CodeGenBuffSave("DateTimeRange "); } | RANGE SIZE { ParserCondPrint("dataTypesRange"); $$.type = SIZERANGETYPE; if( ParserLevelGet() == 0 ) CodeGenBuffSave("static "); CodeGenBuffSave("SizeRange "); } ; /*def data types Range*/ defRange: dataTypesRange IDENT { $2.type = $1.type; CodeGenBuffSave((char *)$2.lexeme); } sc { ParserCondPrint("defRange"); if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, ParserLevelGet() ) != NULL ) { SemanticErr(7); } np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), NO); /* NodePrint(np); */ SymTabInsertFront(np); } ; /*statements*/ stats: /*lambda */ { ParserCondPrint("stats"); } | stats stat { ParserCondPrint("stats"); } ; stat: statNop { ParserCondPrint("stat"); } | statExpression { ParserCondPrint("stat"); } | statAssign { ParserCondPrint("stat"); } | statPrint { ParserCondPrint("stat"); } | statWhile { ParserCondPrint("stat"); } | statContinue { ParserCondPrint("stat"); } | statExit { ParserCondPrint("stat"); } | statIf { ParserCondPrint("stat"); } | statReturn { ParserCondPrint("stat"); } | statFor { ParserCondPrint("stat"); } | statForeach { ParserCondPrint("stat"); } | statSwitch { ParserCondPrint("stat"); } | statBreak { ParserCondPrint("stat"); } | block { ParserCondPrint("stat"); } ; statNop: sc { /*NOT Much*/ ParserCondPrint("statNop"); SemanticStatNopCk(); } ; statAssign: var eqs expr { if( $1.type == STRINGTYPE ) { CodeGenBuffSaveStrAssign(); } } sc { /*will have Sematic check case for each type*/ ParserCondPrint("statAssign"); SemanticStatAssignCk($1, $3); if( $1.type == STRINGTYPE && \ NodeFunDescrFindByLexeme( ParserCurrFunPtrGet(), (char *)$1.lexeme ) != NULL ) SemanticErr(30); if( $1.type == STRINGTYPE ) { if( SymTabFindNodeByLexemeInLevel( (char *)$1.lexeme, 0 ) == NULL ) { CodeGenBuffSave("varstrModScope("); CodeGenBuffSave((char *)$1.lexeme); CodeGenBuffSave(", "); sprintf(bufstr, "%d", ParserVarScopeGet()); CodeGenBuffSave(bufstr); CodeGenBuffSave(");"); CodeGenBuffSave("\n"); } CodeGenBuffSave("varstrFreeByScope(-1);"); CodeGenBuffSave("\n"); CodeGenBuffEmit(); } else if ( $1.type == QUETYPE ) { CodeGenBuffSave("mallocTableSafeModScope("); CodeGenBuffSave((char *)$1.lexeme); CodeGenBuffSave(", "); if( SymTabFindNodeByLexemeInLevel( (char *)$1.lexeme, 0 ) != NULL ) { CodeGenBuffSave("0"); } else { sprintf(bufstr, "%d", ParserVarScopeGet()); CodeGenBuffSave(bufstr); } CodeGenBuffSave(");"); CodeGenBuffSave("\n"); CodeGenBuffSave("mallocTableFreeByScope(-1, QueFree);"); CodeGenBuffSave("\n"); CodeGenBuffEmit(); } } ; statExpression: expr sc { ParserCondPrint("statExpression"); if( $1.type == STRINGTYPE ) { CodeGenBuffSave("varstrFreeByScope(-1);"); CodeGenBuffSave("\n"); } else if( $1.type == QUETYPE ) { CodeGenBuffSave("mallocTableFreeByScope(-1, QueFree);"); CodeGenBuffSave("\n"); } } ; /* * CodeGen will produce print stat based * the type of var. * See outline for CodeGenPrintVar() in CodeGen.fun. * OK: all simple, Job, Que, Node * OK: range of simples * Not: Setof X */ statPrint: PRINT { } statPrintTail { ParserCondPrint("statPrint"); CodeGenBuffSave("printf(\"\\n\");"); CodeGenBuffSave("\n"); CodeGenBuffEmit(); } ; statPrintTail: lb var rb { ParserCondPrint("statPrintTail"); SemanticStatPrintTailCk($2); CodeGenStatPrintTail($2); } sc { ParserCondPrint("statPrintTail"); } | lb consts rb { ParserCondPrint("statPrintTail"); SemanticStatPrintTailCk($2); CodeGenStatPrintTail($2); } sc { ParserCondPrint("statPrintTail"); } ; /*make it block */ /*block -> { stat } anyway */ /*Ok: INT, Float */ /*Semantic check*/ statWhile: statWhileHead block { ParserCondPrint("statWhile"); inLoop--; } ; statWhileHead: WHILE { CodeGenBuffSave("while"); inLoop++; } lb expr rb { ParserCondPrint("statWhileHead"); SemanticStatWhileHeadCk($4); } ; /*make it block */ /*block -> { stat } anyway */ /*Ok: INT, Float */ /*Semantic check*/ statIf: statIfHead block { ParserCondPrint("statIf"); } | statIfHead block ELSE { CodeGenBuffSave("else"); } block { ParserCondPrint("statIf"); } ; statIfHead: IF { CodeGenBuffSave("if"); } lb expr rb { ParserCondPrint("statIfHead"); SemanticStatIfHeadCk($4); } ; /*Ok: all simple */ /*OK: Node, Que, Job*/ /*Semantic check*/ statReturn: RETURN { CodeGenBuffSave("return"); } statReturnTail { ParserCondPrint("statReturn"); } ; /*Ok: INT, Float */ /*Semantic check*/ statReturnTail: lb var rb { ParserCondPrint("statReturnTail"); SemanticStatReturnTailCk($2); if( $2.type == STRINGTYPE && \ NodeFunDescrFindByLexeme( ParserCurrFunPtrGet(), (char *)$2.lexeme ) == NULL ) { if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, 0 ) == NULL ) { CodeGenBuffSaveBefore("varstrModScope(", "return", CodeGenLastDef("return")); CodeGenBuffSaveAfter((char *)$2.lexeme, "varstrModScope(", CodeGenLastDef("varstrModScope(")); CodeGenBuffSaveAfter("\n", (char *)$2.lexeme, CodeGenLastDef((char *)$2.lexeme)); CodeGenBuffSaveAfter(", -1);", (char *)$2.lexeme, CodeGenLastDef((char *)$2.lexeme)); } } else if( $2.type == QUETYPE ) { if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, 0 ) == NULL ) { CodeGenBuffSaveBefore("mallocTableSafeModScope(", "return", CodeGenLastDef("return")); CodeGenBuffSaveAfter((char *)$2.lexeme, "mallocTableSafeModScope(", CodeGenLastDef("mallocTableSafeModScope(")); CodeGenBuffSaveAfter("\n", (char *)$2.lexeme, CodeGenLastDef((char *)$2.lexeme)); CodeGenBuffSaveAfter(", -1);", (char *)$2.lexeme, CodeGenLastDef((char *)$2.lexeme)); } } /* level 1 is where all local variables are declared */ if( SymTabFindAnyNodeInLevelOfType( 1, STRINGTYPE ) != NULL ) { sprintf(bufstr, "%d", ParserVarScopeGet()); CodeGenBuffSaveBefore("varstrFreeByScope(", "return", CodeGenLastDef("return")); CodeGenBuffSaveAfter(bufstr, "varstrFreeByScope(", CodeGenLastDef("varstrFreeByScope(")); CodeGenBuffSaveAfter("\n", bufstr, CodeGenLastDef(bufstr)); CodeGenBuffSaveAfter(");", bufstr, CodeGenLastDef(bufstr)); } if( SymTabFindAnyNodeInLevelOfType( 1, QUETYPE ) != NULL ) { sprintf(bufstr, "%d", ParserVarScopeGet()); CodeGenBuffSaveBefore("mallocTableFreeByScope(", "return", CodeGenLastDef("return")); CodeGenBuffSaveAfter(bufstr, "mallocTableFreeByScope(", CodeGenLastDef("mallocTableFreeByScope(")); CodeGenBuffSaveAfter("\n", bufstr, CodeGenLastDef(bufstr)); CodeGenBuffSaveAfter(");", bufstr, CodeGenLastDef(bufstr)); CodeGenBuffSaveAfter(", QueFree", bufstr, CodeGenLastDef(bufstr)); } } ';' { ParserCondPrint("statReturnTail"); CodeGenBuffSave(";"); CodeGenBuffSave("\n"); } | lb consts rb { ParserCondPrint("statReturnTail"); /* Let's allow a constant string value return if($2.type == STRINGTYPE) SemanticErr(29); */ SemanticStatReturnTailCk($2); if( SymTabFindAnyNodeInLevelOfType( 1, STRINGTYPE ) != NULL ) { sprintf(bufstr, "%d", ParserVarScopeGet()); CodeGenBuffSaveBefore("varstrFreeByScope(", "return", CodeGenLastDef("return")); CodeGenBuffSaveAfter(bufstr, "varstrFreeByScope(", CodeGenLastDef("varstrFreeByScope(")); CodeGenBuffSaveAfter("\n", bufstr, CodeGenLastDef(bufstr)); CodeGenBuffSaveAfter(");", bufstr, CodeGenLastDef(bufstr)); } if( SymTabFindAnyNodeInLevelOfType( 1, QUETYPE ) != NULL ) { sprintf(bufstr, "%d", ParserVarScopeGet()); CodeGenBuffSaveBefore("mallocTableFreeByScope(", "return", CodeGenLastDef("return")); CodeGenBuffSaveAfter(bufstr, "mallocTableFreeByScope(", CodeGenLastDef("mallocTableFreeByScope(")); CodeGenBuffSaveAfter("\n", bufstr, CodeGenLastDef(bufstr)); CodeGenBuffSaveAfter(");", bufstr, CodeGenLastDef(bufstr)); CodeGenBuffSaveAfter(", QueFree", bufstr, CodeGenLastDef(bufstr)); } } ';' { ParserCondPrint("statReturnTail"); CodeGenBuffSave(";"); CodeGenBuffSave("\n"); } | '(' ')' { ParserCondPrint("statReturnTail"); if( (np = ParserCurrFunPtrGet()) == NULL ) SemanticErr(2); if( NodeGetType(np) != VOIDTYPE ) SemanticErr(11); if( SymTabFindAnyNodeInLevelOfType( 1, STRINGTYPE ) != NULL ) { sprintf(bufstr, "%d", ParserVarScopeGet()); CodeGenBuffSaveBefore("varstrFreeByScope(", "return", CodeGenLastDef("return")); CodeGenBuffSaveAfter(bufstr, "varstrFreeByScope(", CodeGenLastDef("varstrFreeByScope(")); CodeGenBuffSaveAfter("\n", bufstr, CodeGenLastDef(bufstr)); CodeGenBuffSaveAfter(");", bufstr, CodeGenLastDef(bufstr)); } if( SymTabFindAnyNodeInLevelOfType( 1, QUETYPE ) != NULL ) { sprintf(bufstr, "%d", ParserVarScopeGet()); CodeGenBuffSaveBefore("mallocTableFreeByScope(", "return", CodeGenLastDef("return")); CodeGenBuffSaveAfter(bufstr, "mallocTableFreeByScope(", CodeGenLastDef("mallocTableFreeByScope(")); CodeGenBuffSaveAfter("\n", bufstr, CodeGenLastDef(bufstr)); CodeGenBuffSaveAfter(");", bufstr, CodeGenLastDef(bufstr)); CodeGenBuffSaveAfter(", QueFree", bufstr, CodeGenLastDef(bufstr)); } } ';' { ParserCondPrint("statReturnTail"); CodeGenBuffSave(";"); CodeGenBuffSave("\n"); } ; /*make it block */ /*block -> { stat } anyway */ /*Ok: INT, Float */ /*Semantic check*/ statFor: statForHead block { ParserCondPrint("statFor"); inLoop--; } ; statForHead: FOR { CodeGenBuffSave("for"); inLoop++; } lb statForAssign ';' { ParserCondPrint("statForHead"); CodeGenBuffSave("; "); } var cprOp expr ';' { ParserCondPrint("statForHead"); CodeGenBuffSave("; "); } statForAssign rb { ParserCondPrint("statForHead"); SemanticStatForHeadCk($7, $9); } ; statForAssign: var eqs expr { ParserCondPrint("statForAssign"); SemanticStatForAssignCk($1, $3); } | var POSTOP { ParserCondPrint("statForAssign"); SemanticStatForPostAssignCk($1); CodeGenBuffSave((char *)$2.lexeme); } ; cprOp: LE { ParserCondPrint("cprOp"); CodeGenBuffSave(" <= "); } | LT { ParserCondPrint("cprOp"); CodeGenBuffSave(" < "); } | GE { ParserCondPrint("cprOp"); CodeGenBuffSave( " >= "); } | GT { ParserCondPrint("cprOp"); CodeGenBuffSave(" > "); } | EQ { ParserCondPrint("cprOp"); CodeGenBuffSave(" == "); } | NEQ { ParserCondPrint("cprOp"); CodeGenBuffSave(" != "); } ; /*make it block */ /*block -> { stat } anyway */ /* * OK:q,j,n,cpu in JOBSET, QUESET, NODESET, CPUSET. * OK: int, float, dayofweek, date, time in RANGE of X. */ statForeach: statForeachHead block { ParserCondPrint("statForeach"); inLoop--; } ; statForeachHead: FOREACH { inLoop++; } lb var IN var rb { ParserCondPrint("statForeachHead"); SemanticStatForeachHeadCk($4, $6); CodeGenBuffSaveForeach($4, $6); } ; /*semantic check*/ /* * allow var int, float, dayofwekk, date, time. * Range int, float, dayofweek, date, time * */ statSwitch: caseSwitchHead '{' { ParserLevelIncr(); } caseList defCase '}' { SymTabDeleteLevel(ParserLevelGet()); ParserLevelDecr(); ParserCondPrint("statSwitch"); inSwitch--; /* delete remaining switch if any */ CodeGenBuffDelete("switch", CodeGenLastDef("switch")); } ; /*semantic check*/ /* * allow var int, float, dayofwekk, date, time. * Range int, float, dayofweek, date, time * */ caseSwitchHead: SWITCH lb var rb { inSwitch++; ParserCondPrint("caseSwitchHead"); if( $3.type == VOIDTYPE ) SemanticErr(1); ParserCurrSwitchVarPut($3); CodeGenBuffClear(); CodeGenBuffSave("switch"); } ; caseList: /*lambda*/ { ParserCondPrint("caseList"); } | caseList caseElement { ParserCondPrint("caseList"); } ; defCase: /* lambda */ { ParserCondPrint("defCase"); } | DEFAULT ':' { ParserCondPrint("defCase"); intval = CodeGenLastDef("switch"); if( intval == 0 ) CodeGenBuffSave("else"); else { CodeGenBuffDelete("switch", intval); CodeGenBuffSave("if(1)"); } } block { ParserCondPrint("defCase"); } ; /* * need two types of elt. * FirstCaseElt & NextCaseElt to include "else" in front. * * Alternate need typicalElt (has trailing else), and lastElt (no else). */ /*make it block */ /*block -> { stat } anyway */ caseElement: caseElementHead block { ParserCondPrint("caseElement"); } ; /* * need two types of elt. * FirstCaseElt & NextCaseElt to include "else" in front. * * Alternate need typicalElt (has trailing else), and lastElt (no else). */ /*make it block */ /*block -> { stat } anyway */ caseElementHead: CASE intConst ':' { ParserCondPrint("caseElementHead"); ParserCondPrint(":"); SemanticCaseTypeCk($2); if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, ParserLevelGet() ) != NULL ) { SemanticErr(12); } np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), NO); /* NodePrint(np); */ SymTabInsertFront(np); CodeGenBuffSaveSwitch(ParserCurrSwitchVarGet()); } | CASE floatConst ':' { ParserCondPrint("caseElementHead"); ParserCondPrint(":"); SemanticCaseTypeCk($2); if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, ParserLevelGet() ) != NULL ) { SemanticErr(12); } np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), NO); /* NodePrint(np); */ SymTabInsertFront(np); CodeGenBuffSaveSwitch(ParserCurrSwitchVarGet()); } | CASE dayofweekConst ':' { ParserCondPrint("caseElementHead"); ParserCondPrint(":"); SemanticCaseTypeCk($2); if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, ParserLevelGet() ) != NULL ) { SemanticErr(12); } np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), NO); /* NodePrint(np); */ SymTabInsertFront(np); CodeGenBuffSaveSwitch(ParserCurrSwitchVarGet()); } | CASE datetimeConst ':' { ParserCondPrint("caseElementHead"); ParserCondPrint(":"); SemanticCaseTypeCk($2); if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, ParserLevelGet() ) != NULL ) { SemanticErr(12); } np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), NO); /* NodePrint(np); */ SymTabInsertFront(np); CodeGenBuffSaveSwitch(ParserCurrSwitchVarGet()); } | CASE sizeConst ':' { ParserCondPrint("caseElementHead"); ParserCondPrint(":"); SemanticCaseTypeCk($2); if( SymTabFindNodeByLexemeAndTypeInLevel( (char *)$2.lexeme, ParserLevelGet(), SIZETYPE, sizeStrcmp ) != NULL ) { SemanticErr(12); } np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), NO); /* NodePrint(np); */ SymTabInsertFront(np); CodeGenBuffSaveSwitch(ParserCurrSwitchVarGet()); } | CASE stringConst ':' { ParserCondPrint("caseElementHead"); ParserCondPrint(":"); SemanticCaseTypeCk($2); if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, ParserLevelGet() ) != NULL ) { SemanticErr(12); } np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), NO); /* NodePrint(np); */ SymTabInsertFront(np); CodeGenBuffSaveSwitch(ParserCurrSwitchVarGet()); } | CASE serverConst ':' { ParserCondPrint("caseElementHead"); ParserCondPrint(":"); SemanticCaseTypeCk($2); if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, ParserLevelGet() ) != NULL ) { SemanticErr(12); } np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), NO); /* NodePrint(np); */ SymTabInsertFront(np); CodeGenBuffSaveSwitch(ParserCurrSwitchVarGet()); } | CASE queConst ':' { ParserCondPrint("caseElementHead"); ParserCondPrint(":"); SemanticCaseTypeCk($2); if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, ParserLevelGet() ) != NULL ) { SemanticErr(12); } np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), NO); /* NodePrint(np); */ SymTabInsertFront(np); CodeGenBuffSaveSwitch(ParserCurrSwitchVarGet()); } | CASE jobConst ':' { ParserCondPrint("caseElementHead"); ParserCondPrint(":"); SemanticCaseTypeCk($2); if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, ParserLevelGet() ) != NULL ) { SemanticErr(12); } np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), NO); /* NodePrint(np); */ SymTabInsertFront(np); CodeGenBuffSaveSwitch(ParserCurrSwitchVarGet()); } | CASE cnodeConst ':' { ParserCondPrint("caseElementHead"); ParserCondPrint(":"); SemanticCaseTypeCk($2); if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, ParserLevelGet() ) != NULL ) { SemanticErr(12); } np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), NO); /* NodePrint(np); */ SymTabInsertFront(np); CodeGenBuffSaveSwitch(ParserCurrSwitchVarGet()); } | CASE IN constRange ':' { ParserCondPrint("caseElementHead"); ParserCondPrint(":"); SemanticCaseInTypeCk($3); if( $3.type == SIZERANGETYPE ) { if( SymTabFindNodeByLexemeAndTypeInLevel( (char *)$3.lexeme, ParserLevelGet(), SIZERANGETYPE, sizeRangeStrcmp ) != NULL ) { SemanticErr(12); } } else { if( SymTabFindNodeByLexemeInLevel( (char *)$3.lexeme, ParserLevelGet() ) != NULL ) { SemanticErr(12); } } np = NodeNew( (char *) $3.lexeme, $3.type, $3.line, ParserLevelGet(), NO); /* NodePrint(np); */ SymTabInsertFront(np); CodeGenBuffSaveSwitchIn(ParserCurrSwitchVarGet(), $3); } /* * Use semantics cases distinguish betw Set & Range. * To have seperate rule for Set & Range creates red/red conf. */ /* * We **only** have var IN RANGE. (the only var permitted). * Use Semantics to check Range type. * Maybe, const Range also. */ | CASE IN var ':' { ParserCondPrint("caseElementHead"); ParserCondPrint(":"); SemanticCaseInTypeCk($3); if( SymTabFindNodeByLexemeInLevel( (char *)$3.lexeme, ParserLevelGet() ) != NULL ) { SemanticErr(12); } np = NodeNew( (char *) $3.lexeme, $3.type, $3.line, ParserLevelGet(), NO); /* NodePrint(np); */ SymTabInsertFront(np); SemanticCaseInVarCk($3); CodeGenBuffSaveSwitchIn(ParserCurrSwitchVarGet(), $3); } ; /*break*/ statBreak: BREAK ';' { ParserCondPrint("statBreak"); if( !inLoop ) SemanticErr(14); CodeGenBuffSave((char *)$1.lexeme); CodeGenBuffSave(";"); CodeGenBuffSave("\n"); CodeGenBuffEmit(); } ; statContinue: CONTINUE ';' { ParserCondPrint("statContinue"); if( !inLoop ) SemanticErr(15); CodeGenBuffSave((char *)$1.lexeme); CodeGenBuffSave(";"); CodeGenBuffSave("\n"); CodeGenBuffEmit(); } ; statExit: EXIT lb intConst rb ';' { ParserCondPrint("statExit"); CodeGenBuffSaveBefore("exit", "(", CodeGenLastDef("(")); CodeGenBuffSave(";"); CodeGenBuffSave("\n"); if( SymTabFindAnyNodeInLevelOfType( 1, STRINGTYPE ) != NULL ) { sprintf(bufstr, "%d", ParserVarScopeGet()); CodeGenBuffSaveBefore("varstrFreeByScope(", "exit", CodeGenLastDef("exit")); CodeGenBuffSaveAfter(bufstr, "varstrFreeByScope(", CodeGenLastDef("varstrFreeByScope(")); CodeGenBuffSaveAfter("\n", bufstr, CodeGenLastDef(bufstr)); CodeGenBuffSaveAfter(");", bufstr, CodeGenLastDef(bufstr)); } if( SymTabFindAnyNodeInLevelOfType( 1, QUETYPE ) != NULL ) { sprintf(bufstr, "%d", ParserVarScopeGet()); CodeGenBuffSaveBefore("mallocTableFreeByScope(", "exit", CodeGenLastDef("exit")); CodeGenBuffSaveAfter(bufstr, "mallocTableFreeByScope(", CodeGenLastDef("mallocTableFreeByScope(")); CodeGenBuffSaveAfter("\n", bufstr, CodeGenLastDef(bufstr)); CodeGenBuffSaveAfter(");", bufstr, CodeGenLastDef(bufstr)); CodeGenBuffSaveAfter(", QueFree", bufstr, CodeGenLastDef(bufstr)); } } ; /*param lists*/ /*can be almost any type, int, Range of int, ptrToFun, etc */ /* Not Set. Use global Set var if needed. */ /* Semantics analyser check valid args */ params: /*lambda*/ { ParserCondPrint("params"); CodeGenBuffDelete("static ", CodeGenLastDef("static ")); } | paramDeclare moreParams { ParserCondPrint("params"); CodeGenBuffDelete("static ", CodeGenLastDef("static ")); } ; /* Prototype definition*/ /* This is serves fun prototype and also fun definition.*/ /* They are handled different */ /* All funs must have fun prototype.*/ /* NASL funs will be defined in NASL prog.*/ /* Some funs will be defined in the support.*/ /* * Ok: Simple, Complex, Range, funCall * Ok: Cpr types: LE, MAX, etc * Not: Set of x. */ /*problem how to specify argument that is a ptr fun */ /*need fun type*/ /*but all (almost) funs are different type -- leave that to semantic analyser*/ /* Check params of use vs declare at first level of fun. For now fun as param, verify sematics only ret type. */ /*param declare pair*/ paramDeclare: dataTypes IDENT { ParserCondPrint("paramDeclare"); /*not here PPT($1) */ $2.type = $1.type; if( NodeFunDescrFindByLexeme( ParserCurrFunPtrGet(), (char *)$2.lexeme ) != NULL ) { SemanticErr(10); } np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), NO); /* NodePrint(np); */ NodePutLevel(np, 1); /* prototyping: needed to check funCall against definition */ SymTabParamLink(ParserCurrFunPtrGet(), np); /* create another node for semantic checking of undefined variables or redeclarations */ np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), NO); NodePutLevel(np, 1); SymTabInsertFront(np); NodeParamCntIncr(ParserCurrFunPtrGet()); CodeGenBuffSave((char *)$2.lexeme); } | FUN dataTypesSimple IDENT { ParserCondPrint("paramDeclare"); $3.type = $2.type; if( NodeFunDescrFindByLexeme( ParserCurrFunPtrGet(), (char *)$3.lexeme ) != NULL ) { SemanticErr(10); } np = NodeNew( (char *) $3.lexeme, $3.type, $3.line, ParserLevelGet(), YES); /* NodePrint(np); */ NodePutLevel(np, 1); /* prototyping: needed to check funCall against definition */ SymTabParamLink(ParserCurrFunPtrGet(), np); /* create another node for semantic checking of undefined variables or redeclarations */ np = NodeNew( (char *) $3.lexeme, $3.type, $3.line, ParserLevelGet(), YES); NodePutLevel(np, 1); SymTabInsertFront(np); NodeParamCntIncr(ParserCurrFunPtrGet()); CodeGenBuffSave("(*"); CodeGenBuffSave((char *)$3.lexeme); CodeGenBuffSave(")()"); } | FUN dataTypesComplex IDENT { ParserCondPrint("paramDeclare"); $3.type = $2.type; if( NodeFunDescrFindByLexeme( ParserCurrFunPtrGet(), (char *)$3.lexeme ) != NULL ) { SemanticErr(10); } np = NodeNew( (char *) $3.lexeme, $3.type, $3.line, ParserLevelGet(), YES); /* NodePrint(np); */ NodePutLevel(np, 1); /* prototyping: needed to check funCall against definition */ SymTabParamLink(ParserCurrFunPtrGet(), np); /* create another node for semantic checking of undefined variables or redeclarations */ np = NodeNew( (char *) $3.lexeme, $3.type, $3.line, ParserLevelGet(), YES); NodePutLevel(np, 1); SymTabInsertFront(np); NodeParamCntIncr(ParserCurrFunPtrGet()); CodeGenBuffSave("(*"); CodeGenBuffSave((char *)$3.lexeme); CodeGenBuffSave(")()"); } | FUN dataTypesSet IDENT { ParserCondPrint("paramDeclare"); $3.type = $2.type; if( NodeFunDescrFindByLexeme( ParserCurrFunPtrGet(), (char *)$3.lexeme ) != NULL ) { SemanticErr(10); } np = NodeNew( (char *) $3.lexeme, $3.type, $3.line, ParserLevelGet(), YES); /* NodePrint(np); */ NodePutLevel(np, 1); /* prototyping: needed to check funCall against definition */ SymTabParamLink(ParserCurrFunPtrGet(), np); /* create another node for semantic checking of undefined variables or redeclarations */ np = NodeNew( (char *) $3.lexeme, $3.type, $3.line, ParserLevelGet(), YES); NodePutLevel(np, 1); SymTabInsertFront(np); NodeParamCntIncr(ParserCurrFunPtrGet()); CodeGenBuffSave("(*"); CodeGenBuffSave((char *)$3.lexeme); CodeGenBuffSave(")()"); } ; moreParams: /*lambda*/ { ParserCondPrint("moreParams"); CodeGenBuffDelete("static ", CodeGenLastDef("static ")); } | comma { ParserCondPrint(","); } paramDeclare moreParams { ParserCondPrint("moreParams"); CodeGenBuffDelete("static ", CodeGenLastDef("static ")); } ; /*Semantic must check ADT validity of op on type*/ /* In general, verify binary arith * both operands of int or float. */ /*arithmetic*/ expr: expr '+' { ParserCondPrint("+"); if( $1.type == SIZETYPE ) CodeGenBuffSaveSpecOper("sizeAdd( "); else if( $1.type == STRINGTYPE ) CodeGenBuffSaveSpecOper("strCat( "); else CodeGenBuffSave(" + "); } expr { ParserCondPrint("expr"); SemanticStatPlusExprCk($1, $4); if( $1.type == FLOATTYPE || $4.type == FLOATTYPE ) $$.type = FLOATTYPE; else $$.type = $1.type; if( $1.type == SIZETYPE || $1.type == STRINGTYPE ) CodeGenBuffSave(" )"); } | expr '-' { ParserCondPrint("-"); if( $1.type == SIZETYPE ) CodeGenBuffSaveSpecOper("sizeSub( "); else CodeGenBuffSave(" - "); } expr { ParserCondPrint("expr"); SemanticStatMinusExprCk($1, $4); if( $1.type == FLOATTYPE || $4.type == FLOATTYPE ) $$.type = FLOATTYPE; else $$.type = $1.type; if( $1.type == SIZETYPE ) CodeGenBuffSave(" )"); } | expr '*' { ParserCondPrint("*"); if( $1.type == SIZETYPE ) CodeGenBuffSaveSpecOper("sizeMul( "); else CodeGenBuffSave(" * "); } expr { ParserCondPrint("expr"); SemanticStatMultDivExprCk($1, $4); if( $1.type == FLOATTYPE || $4.type == FLOATTYPE ) $$.type = FLOATTYPE; else $$.type = $1.type; if( $1.type == SIZETYPE ) CodeGenBuffSave(" )"); } | expr '/' { ParserCondPrint("/"); if( $1.type == SIZETYPE ) CodeGenBuffSaveSpecOper("sizeDiv( "); else CodeGenBuffSave(" / "); } expr { ParserCondPrint("expr"); SemanticStatMultDivExprCk($1, $4); if( $1.type == FLOATTYPE || $4.type == FLOATTYPE ) $$.type = FLOATTYPE; else $$.type = $1.type; if( $1.type == SIZETYPE ) CodeGenBuffSave(" )"); } | expr '%' { ParserCondPrint("%"); CodeGenBuffSave(" % "); } expr { $$.type = $1.type; ParserCondPrint("expr"); SemanticStatModulusExprCk($1, $4); } /* For UMINUS and UPLUS, put an enclosing '()' during CodeGen (i.e. -5 should be written as (-5) */ /* another trick is to start with a space...'-6' should be ' -6' */ /* this is needed to disambiguate. Some C compiler will accept 6+ +3, */ /* 6+(+3) but not 6++3 */ | '-' { ParserCondPrint("-"); CodeGenBuffSave("-"); } expr %prec UMINUS { $$.type = $3.type; ParserCondPrint("expr"); SemanticStatUnaryExprCk($3); if( $3.type == SIZETYPE ) { CodeGenBuffSaveAfter("sizeUminus(", "-", CodeGenLastDef("-")); CodeGenBuffSave(")"); CodeGenBuffDelete("-", CodeGenLastDef("-")); } } /* a UPLUS is needed to balance UMINUS and to resolve i=i+1 */ | '+' { ParserCondPrint("+"); CodeGenBuffSave("+"); } expr %prec UPLUS { $$.type = $3.type; ParserCondPrint("expr"); SemanticStatUnaryExprCk($3); if( $3.type == SIZETYPE ) CodeGenBuffDelete("+", CodeGenLastDef("+")); } /*compares*/ /* simple operands int, float, strings. * complex types, Job j, if (j == NULL). */ | expr EQ { ParserCondPrint("EQ"); switch($1.type) { case DATETIMETYPE: CodeGenBuffSaveSpecOper("datetimecmp( "); break; case STRINGTYPE: CodeGenBuffSaveSpecOper("STRCMP( "); CodeGenBuffSave(" ==, "); break; case SIZETYPE: CodeGenBuffSaveSpecOper("sizecmp( "); break; default: CodeGenBuffSave(" == "); } } expr { $$.type = INTTYPE; ParserCondPrint("expr"); SemanticStatCompExprCk($1, $4); if( $1.type == DATETIMETYPE || \ $1.type == SIZETYPE ) { CodeGenBuffSave(" )"); CodeGenBuffSave(" == 0"); } else if( $1.type == STRINGTYPE ) { CodeGenBuffSave(" )"); } } | expr NEQ { ParserCondPrint("NEQ"); switch($1.type) { case DATETIMETYPE: CodeGenBuffSaveSpecOper("datetimecmp( "); break; case STRINGTYPE: CodeGenBuffSaveSpecOper("STRCMP( "); CodeGenBuffSave(" !=, "); break; case SIZETYPE: CodeGenBuffSaveSpecOper("sizecmp( "); break; default: CodeGenBuffSave(" != "); } } expr { $$.type = INTTYPE; ParserCondPrint("expr"); SemanticStatCompExprCk($1, $4); if( $1.type == DATETIMETYPE || \ $1.type == SIZETYPE ) { CodeGenBuffSave(" )"); CodeGenBuffSave(" != 0"); } else if( $1.type == STRINGTYPE ) { CodeGenBuffSave(" )"); } } | expr LT { ParserCondPrint("LT"); switch($1.type) { case DATETIMETYPE: CodeGenBuffSaveSpecOper("datetimecmp( "); break; case STRINGTYPE: CodeGenBuffSaveSpecOper("STRCMP( "); CodeGenBuffSave(" <, "); break; case SIZETYPE: CodeGenBuffSaveSpecOper("sizecmp( "); break; default: CodeGenBuffSave(" < "); } } expr { $$.type = INTTYPE; ParserCondPrint("expr"); SemanticStatCompExprCk($1, $4); if( $1.type == DATETIMETYPE || \ $1.type == SIZETYPE ) { CodeGenBuffSave(" )"); CodeGenBuffSave(" < 0"); } else if( $1.type == STRINGTYPE ) { CodeGenBuffSave(" )"); } } | expr LE { ParserCondPrint("LE"); switch($1.type) { case DATETIMETYPE: CodeGenBuffSaveSpecOper("datetimecmp( "); break; case STRINGTYPE: CodeGenBuffSaveSpecOper("STRCMP( "); CodeGenBuffSave(" <=, "); break; case SIZETYPE: CodeGenBuffSaveSpecOper("sizecmp( "); break; default: CodeGenBuffSave(" <= "); } } expr { $$.type = INTTYPE; ParserCondPrint("expr"); SemanticStatCompExprCk($1, $4); if( $1.type == DATETIMETYPE || \ $1.type == SIZETYPE ) { CodeGenBuffSave(" )"); CodeGenBuffSave(" <= 0"); } else if( $1.type == STRINGTYPE ) { CodeGenBuffSave(" )"); } } | expr GT { ParserCondPrint("GT"); switch($1.type) { case DATETIMETYPE: CodeGenBuffSaveSpecOper("datetimecmp( "); break; case STRINGTYPE: CodeGenBuffSaveSpecOper("STRCMP( "); CodeGenBuffSave(" >, "); break; case SIZETYPE: CodeGenBuffSaveSpecOper("sizecmp( "); break; default: CodeGenBuffSave(" > "); } } expr { $$.type = INTTYPE; ParserCondPrint("expr"); SemanticStatCompExprCk($1, $4); if( $1.type == DATETIMETYPE || \ $1.type == SIZETYPE ) { CodeGenBuffSave(" )"); CodeGenBuffSave(" > 0"); } else if( $1.type == STRINGTYPE ) { CodeGenBuffSave(" )"); } } | expr GE { ParserCondPrint("GE"); switch($1.type) { case DATETIMETYPE: CodeGenBuffSaveSpecOper("datetimecmp( "); break; case STRINGTYPE: CodeGenBuffSaveSpecOper("STRCMP( "); CodeGenBuffSave(" >=, "); break; case SIZETYPE: CodeGenBuffSaveSpecOper("sizecmp( "); break; default: CodeGenBuffSave(" >= "); } } expr { $$.type = INTTYPE; ParserCondPrint("expr"); SemanticStatCompExprCk($1, $4); if( $1.type == DATETIMETYPE || \ $1.type == SIZETYPE ) { CodeGenBuffSave(" )"); CodeGenBuffSave(" >= 0"); } else if( $1.type == STRINGTYPE ) { CodeGenBuffSave(" )"); } } | expr AND { ParserCondPrint("AND"); CodeGenBuffSave(" && "); } expr { $$.type = INTTYPE; ParserCondPrint("expr"); SemanticStatAndOrExprCk($1, $4); } | expr OR { ParserCondPrint("OR"); CodeGenBuffSave(" || "); } expr { $$.type = INTTYPE; ParserCondPrint("expr"); SemanticStatAndOrExprCk($1, $4); } | '!' { ParserCondPrint("!"); CodeGenBuffSave("!"); } expr %prec NOT { $$.type = INTTYPE; ParserCondPrint("expr"); SemanticStatNotExprCk($3); } | var POSTOP { ParserCondPrint("POSTOP"); CodeGenBuffSave((char *)$2.lexeme); $$.type = $1.type; ParserCondPrint("expr"); SemanticStatPostOpExprCk($1); } | lb expr rb { $$.type = $2.type; ParserCondPrint("expr"); } | exprTerms { $$.type = $1.type; ParserCondPrint("expr"); /* no need to xfer type -- auto --confired*/ } ; exprTerms: consts { $$.type = $1.type; ParserCondPrint("expr"); /* no need to xfer type -- auto --confired*/ } | funCall { $$.type = $1.type; /*for this purpose, use fun ret type */ /*Do not use the type FUNTYPE */ ParserCondPrint("expr"); } | var { /*lokk up var in ST, then get type*/ /*leave the Semantic checking to R1 var->ID*/ /*assume the R1 found ID in ST and also xferred type to var*/ $$.type = $1.type; ParserCondPrint("expr"); } ; consts: intConst { ParserCondPrint("consts"); $$.type = $1.type; /* no need for type xfer; type etc transferred auto*/ /*$$.type = $1.type;*/ } | floatConst { ParserCondPrint("consts"); $$.type = $1.type; } | dayofweekConst { ParserCondPrint("consts"); $$.type = $1.type; } | datetimeConst { ParserCondPrint("consts"); $$.type = $1.type; } | stringConst { ParserCondPrint("consts"); $$.type = $1.type; } | sizeConst { ParserCondPrint("consts"); $$.type = $1.type; } | constRange { ParserCondPrint("consts"); $$.type = $1.type; } | serverConst { ParserCondPrint("consts"); $$.type = $1.type; } | queConst { ParserCondPrint("consts"); $$.type = $1.type; } | jobConst { ParserCondPrint("consts"); $$.type = $1.type; } | cnodeConst { ParserCondPrint("consts"); $$.type = $1.type; } | setServerConst { ParserCondPrint("consts"); $$.type = $1.type; } | setQueConst { ParserCondPrint("consts"); $$.type = $1.type; } | setJobConst { ParserCondPrint("consts"); $$.type = $1.type; } | setCnodeConst { ParserCondPrint("consts"); $$.type = $1.type; } ; constRange: intConstRange { ParserCondPrint("constRange"); $$.type = $1.type; strcpy($$.lexeme, $1.lexeme); } | floatConstRange { ParserCondPrint("constRange"); $$.type = $1.type; strcpy($$.lexeme, $1.lexeme); } | dayofweekConstRange { ParserCondPrint("constRange"); $$.type = $1.type; strcpy($$.lexeme, $1.lexeme); } | datetimeConstRange { ParserCondPrint("constRange"); $$.type = $1.type; strcpy($$.lexeme, $1.lexeme); } | sizeConstRange { ParserCondPrint("constRange"); $$.type = $1.type; strcpy($$.lexeme, $1.lexeme); } ; intConst: INTCONST { ParserCondPrint("intConst"); $1.type = INTTYPE; /*semantic type*/ $$.type = INTTYPE; /*semantic type*/ if( strcmp($1.lexeme, "SUCCESS") == 0 || \ strcmp($1.lexeme, "FAIL") == 0 || \ strcmp($1.lexeme, "SERVER_ACTIVE") == 0 || \ strcmp($1.lexeme, "SERVER_IDLE") == 0 || \ strcmp($1.lexeme, "SERVER_SCHED") == 0 || \ strcmp($1.lexeme, "SERVER_TERM") == 0 || \ strcmp($1.lexeme, "SERVER_TERMDELAY") == 0 || \ strcmp($1.lexeme, "QTYPE_E") == 0 || \ strcmp($1.lexeme, "QTYPE_R") == 0 || \ strcmp($1.lexeme, "SCHED_DISABLED") == 0 || \ strcmp($1.lexeme, "SCHED_ENABLED") == 0 || \ strcmp($1.lexeme, "FALSE") == 0 || \ strcmp($1.lexeme, "TRUE") == 0 || \ strcmp($1.lexeme, "TRANSIT") == 0 || \ strcmp($1.lexeme, "QUEUED") == 0 || \ strcmp($1.lexeme, "HELD") == 0 || \ strcmp($1.lexeme, "WAITING") == 0 || \ strcmp($1.lexeme, "RUNNING") == 0 || \ strcmp($1.lexeme, "EXITING") == 0 || \ strcmp($1.lexeme, "CNODE_OFFLINE") == 0 || \ strcmp($1.lexeme, "CNODE_DOWN") == 0 || \ strcmp($1.lexeme, "CNODE_FREE") == 0 || \ strcmp($1.lexeme, "CNODE_RESERVE") == 0 || \ strcmp($1.lexeme, "CNODE_INUSE_EXCLUSIVE") == 0 || \ strcmp($1.lexeme, "CNODE_INUSE_SHARED") == 0 || \ strcmp($1.lexeme, "CNODE_TIMESHARED") == 0 || \ strcmp($1.lexeme, "CNODE_CLUSTER") == 0 || \ strcmp($1.lexeme, "CNODE_UNKNOWN") == 0 || \ strcmp($1.lexeme, "SYNCRUN") == 0 || \ strcmp($1.lexeme, "ASYNCRUN") == 0 || \ strcmp($1.lexeme, "DELETE") == 0 || \ strcmp($1.lexeme, "RERUN") == 0 || \ strcmp($1.lexeme, "HOLD") == 0 || \ strcmp($1.lexeme, "RELEASE") == 0 || \ strcmp($1.lexeme, "SIGNAL") == 0 || \ strcmp($1.lexeme, "MODIFYATTR") == 0 || \ strcmp($1.lexeme, "MODIFYRES") == 0 || \ strcmp($1.lexeme, "OP_EQ") == 0 || \ strcmp($1.lexeme, "OP_NEQ") == 0 || \ strcmp($1.lexeme, "OP_LT") == 0 || \ strcmp($1.lexeme, "OP_LE") == 0 || \ strcmp($1.lexeme, "OP_GE") == 0 || \ strcmp($1.lexeme, "OP_GT") == 0 || \ strcmp($1.lexeme, "ASC") == 0 || \ strcmp($1.lexeme, "DESC") == 0 || \ strcmp($1.lexeme, "OP_MAX") == 0 || \ strcmp($1.lexeme, "OP_MIN") == 0 ) strcpy($$.lexeme, $1.lexeme); else sprintf( (char *)$$.lexeme, "%d", strToInt((char *)$1.lexeme)); CodeGenBuffSave((char *)$$.lexeme); } ; floatConst: FLOATCONST { ParserCondPrint("floatConst"); $1.type = FLOATTYPE; /*semantic type*/ $$.type = FLOATTYPE; /*semantic type*/ sprintf( (char *)$$.lexeme, "%f", strToFloat( (char *)$1.lexeme)); /*her we need type xfer, becuase default doesnot happen becuase we doing $1.type = x* in the line above*/ CodeGenBuffSave((char *)$$.lexeme); } ; dayofweekConst: DAYOFWEEKCONST { ParserCondPrint("dayofweekConst"); $1.type = DAYOFWEEKTYPE; $$.type = DAYOFWEEKTYPE; strcpy($$.lexeme, $1.lexeme); CodeGenBuffSave((char *)$$.lexeme); } ; datetimeConst: lb intConst pipe intConst pipe intConst rb { ParserCondPrint("datetimeConst"); $2.type = DATETIMETYPE; $$.type = DATETIMETYPE; sprintf( (char *)$$.lexeme, "%s%s%s%s%s%s%s", $1.lexeme, $2.lexeme, $3.lexeme, $4.lexeme, $5.lexeme, $6.lexeme, $7.lexeme); SemanticDateConstCk($2, $4, $6); CodeGenBuffSaveBefore("strToDateTime(\"", "(", CodeGenLastDef("(")); CodeGenBuffSave("\")"); } | lb intConst colon intConst colon intConst rb { ParserCondPrint("datetimeConst"); $2.type = DATETIMETYPE; $$.type = DATETIMETYPE; sprintf( (char *)$$.lexeme, "%s%s%s%s%s%s%s", $1.lexeme, $2.lexeme, $3.lexeme, $4.lexeme, $5.lexeme, $6.lexeme, $7.lexeme); SemanticTimeConstCk($2, $4, $6); CodeGenBuffSaveBefore("strToDateTime(\"", "(", CodeGenLastDef("(")); CodeGenBuffSave("\")"); } | lb intConst pipe intConst pipe intConst at intConst colon intConst colon intConst rb { ParserCondPrint("datetimeConst"); $2.type = DATETIMETYPE; $$.type = DATETIMETYPE; sprintf( (char *)$$.lexeme, "%s%s%s%s%s%s%s%s%s%s%s%s%s", $1.lexeme, $2.lexeme, $3.lexeme, $4.lexeme, $5.lexeme, $6.lexeme, $7.lexeme, $8.lexeme, $9.lexeme, $10.lexeme, $11.lexeme, $12.lexeme, $13.lexeme); SemanticDateConstCk($2, $4, $6); SemanticTimeConstCk($8, $10, $12); CodeGenBuffSaveBefore("strToDateTime(\"", "(", CodeGenLastDef("(")); CodeGenBuffSave("\")"); } ; stringConst: STRINGCONST { ParserCondPrint("stringConst"); $1.type = STRINGTYPE; $$.type = STRINGTYPE; strcpy($$.lexeme, $1.lexeme); CodeGenBuffSave((char *)$$.lexeme); } ; sizeConst: SIZECONST { ParserCondPrint("sizeConst"); $1.type = SIZETYPE; $$.type = SIZETYPE; strcpy($$.lexeme, $1.lexeme); CodeGenBuffSave("strToSize(\""); CodeGenBuffSave((char *)$$.lexeme); CodeGenBuffSave("\")"); } ; serverConst: SERVERCONST { ParserCondPrint("serverConst"); $1.type = SERVERTYPE; $$.type = SERVERTYPE; strcpy($$.lexeme, $1.lexeme); CodeGenBuffSave((char *)$$.lexeme); } ; jobConst: JOBCONST { ParserCondPrint("jobConst"); $1.type = JOBTYPE; $$.type = JOBTYPE; strcpy($$.lexeme, $1.lexeme); CodeGenBuffSave((char *)$$.lexeme); } ; queConst: QUECONST { ParserCondPrint("queConst"); $1.type = QUETYPE; $$.type = QUETYPE; strcpy($$.lexeme, $1.lexeme); CodeGenBuffSave((char *)$$.lexeme); } ; cnodeConst: CNODECONST { ParserCondPrint("cnodeConst"); $1.type = CNODETYPE; $$.type = CNODETYPE; strcpy($$.lexeme, $1.lexeme); CodeGenBuffSave((char *)$$.lexeme); } setServerConst: SETSERVERCONST { ParserCondPrint("setServerConst"); $1.type = SERVERSETTYPE; $$.type = SERVERSETTYPE; strcpy($$.lexeme, $1.lexeme); CodeGenBuffSave((char *)$$.lexeme); } ; setJobConst: SETJOBCONST { ParserCondPrint("setJobConst"); $1.type = JOBSETTYPE; $$.type = JOBSETTYPE; strcpy($$.lexeme, $1.lexeme); CodeGenBuffSave((char *)$$.lexeme); } ; setQueConst: SETQUECONST { ParserCondPrint("setQueConst"); $1.type = QUESETTYPE; $$.type = QUESETTYPE; strcpy($$.lexeme, $1.lexeme); CodeGenBuffSave((char *)$$.lexeme); } ; setCnodeConst: SETCNODECONST { ParserCondPrint("setCnodeConst"); $1.type = CNODESETTYPE; $$.type = CNODESETTYPE; strcpy($$.lexeme, $1.lexeme); CodeGenBuffSave((char *)$$.lexeme); } ; intConstRange: lb intConst comma intConst rb { ParserCondPrint("intConstRange"); $2.type = INTRANGETYPE; $$.type = INTRANGETYPE; sprintf( (char *)$$.lexeme, "%s%s%s%s%s", $1.lexeme, $2.lexeme, $3.lexeme, $4.lexeme, $5.lexeme); SemanticIntConstRangeCk($2, $4); CodeGenBuffSaveBefore("toIntRange", "(", CodeGenLastDef("(")); } ; floatConstRange: lb floatConst comma floatConst rb { ParserCondPrint("floatConstRange"); $2.type = FLOATRANGETYPE; $$.type = FLOATRANGETYPE; sprintf( (char *)$$.lexeme, "%s%s%s%s%s", $1.lexeme, $2.lexeme, $3.lexeme, $4.lexeme, $5.lexeme); SemanticFloatConstRangeCk($2, $4); CodeGenBuffSaveBefore("toFloatRange", "(", CodeGenLastDef("(")); } ; dayofweekConstRange: lb dayofweekConst comma dayofweekConst rb { ParserCondPrint("dayofweekConstRange"); $2.type = DAYOFWEEKRANGETYPE; $$.type = DAYOFWEEKRANGETYPE; sprintf( (char *)$$.lexeme, "%s%s%s%s%s", $1.lexeme, $2.lexeme, $3.lexeme, $4.lexeme, $5.lexeme); SemanticDayofweekConstRangeCk($2, $4); CodeGenBuffSaveBefore("toDayofweekRange", "(", CodeGenLastDef("(")); } ; datetimeConstRange: lb datetimeConst comma datetimeConst rb { ParserCondPrint("datetimeConstRange"); $2.type = DATETIMERANGETYPE; $$.type = DATETIMERANGETYPE; sprintf( (char *)$$.lexeme, "%s%s%s%s%s", $1.lexeme, $2.lexeme, $3.lexeme, $4.lexeme, $5.lexeme); SemanticDateTimeConstRangeCk($2, $4); /* following resolves conflict when there are inner "("s */ /* the last token should be the ) */ intval = NodeGetLineDef(CodeGenBuffGetLast()); /* find the ( that pairs with the last ) */ CodeGenBuffSaveBefore("toDateTimeRange", "(", intval); } ; sizeConstRange: lb sizeConst comma sizeConst rb { ParserCondPrint("datetimeConstRange"); $2.type = SIZERANGETYPE; $$.type = SIZERANGETYPE; sprintf( (char *)$$.lexeme, "%s%s%s%s%s", $1.lexeme, $2.lexeme, $3.lexeme, $4.lexeme, $5.lexeme); SemanticSizeConstRangeCk($2, $4); /* following resolves conflict when there are inner "("s */ intval = NodeGetLineDef(CodeGenBuffGetLast()); CodeGenBuffSaveBefore("toSizeRange", "(", intval); } ; /*funcall stuff*/ /*no end semic, funCall is expr, and exprStat adds ';' */ /* * Args types: * Ok: Simple, Complex, Range, funCall * Ok: Cpr type: LE, MAX, etc * Not: Set of x. */ funCall: IDENT { /*get type etc by lookup in SymTab */ /* * Let $$ to return type -- not FUNtype. * Get it from SymTab. * This is needed for expr semantic anal. */ /* Check if func is in the symbol table */ if( (np=(Np)SymTabFindNodeByLexemeInProg((char *)$1.lexeme)) == NULL ) { SemanticErr(8); } else { ParserCurrFunParamPtrPut((Np)np); } if( NodeGetFunFlag(np) == YES ) { /* if not internally defined */ strcpy(bufstr2, "basl_"); strcat(bufstr2, $1.lexeme); CodeGenBuffSaveFun((char *)bufstr2); /* save as is */ } else { CodeGenBuffSaveFun((char *)$1.lexeme); /* save as is */ } } lb args rb { ParserCondPrint("funCall"); /*link args*/ /*do not insert IDENT in SymTab-- already is*/ if( (np=(Np)SymTabFindNodeByLexemeInProg((char *)$1.lexeme)) == NULL ) { SemanticErr(8); } else { $$.type = NodeGetType(np); } if( CodeGenLastDef("QueJobFind") != 0 ) { CodeGenBuffSaveQueJobFind(); } else if( CodeGenLastDef("QueFilter") != 0 ) { CodeGenBuffSaveQueFilter(); } else if( CodeGenLastDef("Sort") != 0 ) { if( ParserCurrFunParamPtrGet() != NULL ) SemanticErr(18); CodeGenBuffSaveSort(); } else if( ParserCurrFunParamPtrGet() != NULL ) { SemanticErr(18); } } ; args: /*lambda*/ { /*get type etc from var who gets it from SymTab */ ParserCondPrint("args"); } | arg argList { ParserCondPrint("args"); /*link 1st arg to funname -- need funname*/ /* * Need two ptrs (globals) to arg & param. * Follow chain and cpr types. */ } ; argList: /*lambda*/ { ParserCondPrint("argList"); } | comma arg argList { ParserCondPrint("argList"); } ; /* * Args types: * Ok: Simple, Complex, Range, funCall * Ok: CprType: LE, MAX, etc * Not: Set of x. */ arg: var { ParserCondPrint("arg"); $$.type = $1.type; if( SemanticParamVarCk($1) == GENERICTYPE ) { if( CodeGenLastDef("QueJobFind") != 0 || \ CodeGenLastDef("QueFilter") != 0 ) { if ((np=SymTabFindNodeByLexemeInProg((char *) $1.lexeme)) == NULL) SemanticErr(6); /* QueJobFind and QueFilter's function parameter must accept only */ /* 1 type that is of JOBTYPE */ if( (NodeGetFunFlag(np) != NO ) \ && \ (np->funDescr.paramCnt != 1 || \ NodeGetType(np->funDescr.paramPtr) != JOBTYPE) ) SemanticErr(28); np = NodeNew( (char *)"", $1.type, $1.line, -2, NodeGetFunFlag(np)); SymTabInsertFront(np); } else if ( CodeGenLastDef("Sort") != 0 ) { if ((np=SymTabFindNodeByLexemeInProg((char *) $1.lexeme)) == NULL) SemanticErr(6); /* a key function argument must only accept one argument */ if( NodeGetFunFlag(np) != NO ) { if( NodeGetParamCnt(np) != 1 ) SemanticErr(38); SymTabInsertFront( NodeNew( (char *)"", NodeGetType(np->funDescr.paramPtr), NodeGetLineDef(np->funDescr.paramPtr), -2, NodeGetFunFlag(np->funDescr.paramPtr)) ); } np = NodeNew( (char *)"", $1.type, $1.line, -2, NodeGetFunFlag(np)); SymTabInsertFront(np); } else { /* Level -2 is for temporary/special processing - checking type */ np = NodeNew( (char *)"", $1.type, $1.line, -2, NO); SymTabInsertFront(np); } } } | consts { ParserCondPrint("arg"); $$.type = $1.type; if( SemanticParamConstsCk($1) == GENERICTYPE ) { /* Level -2 is for temporary/special processing - checking type */ np = NodeNew( (char *)"", $1.type, $1.line, -2, NO); SymTabInsertFront(np); } } ; /*var stuff*/ /* * Var types: typeSimple, complex, Range, fun, set * Yes Set. myQs = {"q1", "q2"}; (v2) */ var: IDENT { /*get $1.type by lookup of IDENT in SymTab*/ /*right now $1.t unknown until lookup*/ ParserCondPrint("var"); SemanticVarDefCk($1); /*if all is weel continue else have sem err */ np = SymTabFindNodeByLexemeInProg((char *) $1.lexeme); if (np == NULL) ParserErr(3); /*should not happen since Sem checked this*/ $1.type = NodeGetType(np); $$.type = $1.type; strcpy($$.lexeme, $1.lexeme); /*do not insert IDENT in SymTab-- already is*/ switch( NodeGetFunFlag(np) ) { case YES_INT: case NO: CodeGenBuffSave((char *)$$.lexeme); break; case YES: CodeGenBuffSave("basl_"); CodeGenBuffSave((char *)$$.lexeme); } } ; /*brackets, eqs, etc to order*/ lcb: '{' { ParserCondPrint("lcb"); /* SymTabPrint(); */ CodeGenBuffSave("\n"); CodeGenBuffSave("{"); ParserLevelIncr(); CodeGenBuffSave("\n"); CodeGenBuffSave("\n"); if( inSwitch ) CodeGenBuffSwitchEmit(); else CodeGenBuffEmit(); } ; rcb: '}' { ParserCondPrint("rcb"); if( SymTabFindAnyNodeInLevelOfType( ParserLevelGet(), STRINGTYPE ) != NULL ) { intval = CodeGenLastDef("return") || CodeGenLastDef("exit"); if( intval == 0 ) { /* no previous return/exit statement */ sprintf(bufstr, "%d", ParserVarScopeGet()); CodeGenBuffSave("varstrFreeByScope("); CodeGenBuffSave(bufstr); CodeGenBuffSave(");"); CodeGenBuffSave("\n"); } } if( SymTabFindAnyNodeInLevelOfType( ParserLevelGet(), QUETYPE ) != NULL ) { intval = CodeGenLastDef("return") || CodeGenLastDef("exit"); if( intval == 0 ) { /* no previous return/exit statement */ sprintf(bufstr, "%d", ParserVarScopeGet()); CodeGenBuffSave("mallocTableFreeByScope("); CodeGenBuffSave(bufstr); CodeGenBuffSave(", QueFree"); CodeGenBuffSave(");"); CodeGenBuffSave("\n"); } } /*later must delete levels SymTabDeleteLevel(ParserLevelGet()); */ /* SymTabPrint(); */ SymTabDeleteLevel(ParserLevelGet()); /* SymTabPrint(); */ ParserLevelDecr(); CodeGenBuffSave("}"); CodeGenBuffSave("\n"); if( inSwitch ) CodeGenBuffSwitchEmit(); else CodeGenBuffEmit(); } ; lb: '(' { strcpy($$.lexeme, $1.lexeme); ParserCondPrint("lb"); CodeGenBuffSave("("); } ; rb: ')' { strcpy($$.lexeme, $1.lexeme); ParserCondPrint("rb"); CodeGenBuffSave(")"); } ; comma: ',' { ParserCondPrint("comma"); strcpy($$.lexeme, $1.lexeme); CodeGenBuffSave(", "); } ; colon: ':' { ParserCondPrint("colon"); strcpy($$.lexeme, $1.lexeme); CodeGenBuffSave(":"); } ; pipe: '|' { ParserCondPrint("pipe"); strcpy($$.lexeme, $1.lexeme); CodeGenBuffSave("|"); } ; at: '@' { ParserCondPrint("at"); strcpy($$.lexeme, $1.lexeme); CodeGenBuffSave("@"); } ; eqs: '=' { ParserCondPrint("eqs"); CodeGenBuffSave(" = "); } ; sc: ';' { ParserCondPrint("sc"); CodeGenBuffSave(";"); CodeGenBuffSave("\n"); CodeGenBuffEmit(); } ; defFun: funHead blockWithDefs { ParserCondPrint("defFun"); } ; /*def data types Fun*/ /*can have args int, float, day, Range of Int, prt to functs (funname) */ /*so make params all type, let Semantic analyser check validity*/ /*return type only simple or complex, no set, range */ /* * Set type of ID in token to ret type of fun for semantic anal. * * In STE set funFlag=YES. * * Define glob currFunPtr = SymTabFind($2.lex) to do sem checks. * Use it to cpr proto vs deffun. * Use it tp cpr proto vs funCall. * */ funHead: dataTypesSimple IDENT { $2.type = $1.type; if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, ParserLevelGet() ) != NULL ) { SemanticErr(7); } np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), YES); /* NodePrint(np); */ SymTabInsertFront(np); ParserCurrFunPtrPut(np); /* NodePrint(np); */ CodeGenBuffSave("basl_"); CodeGenBuffSave((char *)$2.lexeme); ParserVarScopeIncr(); } lb params rb { ParserCondPrint("funHead"); /* SymTabPrint(); */ } | dataTypesComplex IDENT { $2.type = $1.type; if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, ParserLevelGet() ) != NULL ) { SemanticErr(7); } np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), YES); /* NodePrint(np); */ SymTabInsertFront(np); ParserCurrFunPtrPut(np); /* NodePrint(np); */ CodeGenBuffSave("basl_"); CodeGenBuffSave((char *)$2.lexeme); ParserVarScopeIncr(); } lb params rb { ParserCondPrint("funHead"); /* SymTabPrint(); */ } | dataTypesSet IDENT { $2.type = $1.type; if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, ParserLevelGet() ) != NULL ) { SemanticErr(7); } np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), YES); /* NodePrint(np); */ SymTabInsertFront(np); ParserCurrFunPtrPut(np); /* NodePrint(np); */ CodeGenBuffSave("basl_"); CodeGenBuffSave((char *)$2.lexeme); ParserVarScopeIncr(); } lb params rb { ParserCondPrint("funHead"); /* SymTabPrint(); */ } ; %% #include /* the master config generated by configure */ #ifndef _POSIX_SOURCE #define _POSIX_SOURCE 1 #endif /* _POSIX_SOURCE */ /* #include "Parser.h" #include "y.tab.h" extern int linenum; extern char linebuf[]; #include extern jmp_buf begin; */ static char ident[] = "@(#) $RCSfile$ $Revision$"; /* GLobal Variables */ FILE * ParserFpOut; /* File Scope Variables */ static char * ParserErrors[] = { "0 no such error msg", "1 ep = NULL", "2 lexem ptr = NULL", "3 np = NULL", "4 ParserFpOut = NULL", "5 str = NULL", "6 string to constant value conversion failed", "" }; static int ParserMaxErrors = 8; static char *ParserName = "Parser"; static int ParserLevel = 0; /*nesting level*/ static int ParserVarScope = 0; /* variable scope */ static struct Node * ParserCurrFunPtr; static struct Node * ParserCurrFunParamPtr; static struct Node * ParserProtoFunPtr; static struct Node * ParserCallFunPtr; static int ParserDF = 0; static struct MYTOK ParserCurrSwitchVar; /*must be here*/ /* remove for DOS */ void yyerror(ep) char *ep; { if(ParserFpOut == NULL) ParserErr(4); fprintf(ParserFpOut, "%d: Error %s in this line:\n%s\n", linenum, ep, linebuf); exit(1); } /* * Work around this Bison */ int yywrap(void) { return(1); } /* * error message and return for new input */ void execError(cp) char *cp; { if(ParserFpOut == NULL) ParserErr(4); fprintf(ParserFpOut, "***rrs Parser run time error: "); fprintf(ParserFpOut, "%s near line %d\n", cp, linenum); ++linenum; longjmp(begin, 0); /* return for next expression */ } /* * Redefined FPE handler */ void ParserFpeCatch(void) { execError("***rrs Parser floating point error\n"); } void ParserInit(void) { ParserCondPrint("ParserInit"); /* ParserDF = 1; */ ParserLevel = 0; ParserVarScope = 0; } /* * Print Token in Bison */ void ParserPrintToken(lexem, lin, len, typ) char *lexem; int lin; int len; int typ; { ParserCondPrint("ParserPrintToken"); if(ParserFpOut == NULL) ParserErr(4); if(ParserDF == 1) { if(lexem == NULL) ParserErr(2); fprintf(ParserFpOut, "lexem=%s, lin=%d, len=%d, typ=%d\n", lexem, lin, len, typ); } } /* * Print Token in Bison */ void ParserPrintToken2(tok) struct MYTOK tok; { ParserCondPrint("ParserPrintToken2"); if(ParserFpOut == NULL) ParserErr(4); if (ParserDF == 1) { fprintf(ParserFpOut, "lexem=%s, lin=%d, len=%d, typ=%d, varFlag=%d\n", tok.lexeme, tok.line, tok.len, tok.type, tok.varFlag); } } /* use for copy mytok -> sym */ /* void ParserTokenToNode(lexem, lin, len, typ) char *lexem; int lin; int len; int typ; { ParserCondPrint("ParserTokenToNode"); if(lexem == NULL) ParserErr(2); np = NodeNew strcpy((char *) yylval.mytok.lexeme, lexem); yylval.mytok.line = lin; yylval.mytok.len = len; yylval.mytok.type = typ; } */ void ParserPutDF(df) int df; { ParserCondPrint("ParserPutDF"); ParserDF = df; } void ParserLevelIncr(void) { ParserCondPrint("ParserLevelIncr"); if(ParserFpOut == NULL) ParserErr(4); ParserLevel++; if( ParserDF == 1 ) fprintf(ParserFpOut, "linenum=%d, level=%d\n", linenum, ParserLevel); } void ParserLevelDecr(void) { ParserCondPrint("ParserLevelDecr"); if(ParserFpOut == NULL) ParserErr(4); ParserLevel--; if( ParserDF == 1 ) fprintf(ParserFpOut, "linenum=%d, level=%d\n", linenum, ParserLevel); } int ParserLevelGet(void) { ParserCondPrint("ParserLevelGet"); return(ParserLevel); } void ParserVarScopeIncr(void) { ParserCondPrint("ParserVarScopeIncr"); ParserVarScope++; } int ParserVarScopeGet(void) { ParserCondPrint("ParserVarScopeGet"); return(ParserVarScope); } void ParserCondPrint(str) char *str; { if(ParserFpOut == NULL) ParserErr(4); if(str == NULL) ParserErr(5); if (ParserDF ==1) { fprintf(ParserFpOut, "%s\t", ParserName); fprintf(ParserFpOut, "%s\n", str); } } void ParserErr(e) int e; { fprintf(ParserFpOut, "ParserErr\n"); if(ParserFpOut == NULL) ParserErr(4); if (e >= ParserMaxErrors) e = 0; fprintf(ParserFpOut, "rs: %s\n", ParserErrors[e]); exit(1); } void ParserPrint(void) { ParserCondPrint("ParserPrint"); fprintf(ParserFpOut, "CurrFunPtr=%x, ProtoFunPtr=%x, CallFunPtr=%x\n", ParserCurrFunPtr , ParserProtoFunPtr , ParserCallFunPtr); } void ParserCurrFunPtrPut(np) Np np; { ParserCondPrint("ParserCurrFunPtrPut"); ParserCurrFunPtr = np; } Np ParserCurrFunPtrGet(void) { ParserCondPrint("ParserCurrFunPtrGet"); return(ParserCurrFunPtr); } void ParserCurrFunParamPtrPut(np) Np np; { ParserCondPrint("ParserCurrFunParamPtrPut"); if( np == NULL ) ParserErr(3); ParserCurrFunParamPtr = np->funDescr.paramPtr; } Np ParserCurrFunParamPtrGet(void) { ParserCondPrint("ParserCurrFunParamPtrGet"); /* printf("CURRENT PARAM: \n"); NodePrint(ParserCurrFunParamPtr); printf("CURRENT PARAM: \n\n"); */ return(ParserCurrFunParamPtr); } void ParserCurrSwitchVarPut(token) struct MYTOK token; { ParserCondPrint("ParserCurrSwitchVarPut"); ParserCurrSwitchVar = token; } struct MYTOK ParserCurrSwitchVarGet(void) { ParserCondPrint("ParserCurrSwitchVarGet"); return(ParserCurrSwitchVar); }