bool parserCls::factor(void) { EtokenType lTt1 = getTokenType();bool bb1 = true ; tokenContainCls lTc1 =getCurToken() ,lTc2;bool seeUnary= false; if( (lTt1 == Plus) || (lTt1==Minus) || (lTt1 == Not) ) { if(lTt1== Plus) lTc1.type = UnaryPlus; else if(lTt1== Minus) lTc1 . type = UnaryMinus; lTc2=lTc1;getToken();lTt1=getTokenType(); lTc1=getCurToken();seeUnary=true; } switch(lTt1){ case OrdNumber:case SciNumber:case Array : addOperand() ;exprFound = true ;needOperand = false ;getToken(); break ; case String : if(seeUnary) {errorUnary(lTc2 ,1);bb1 = false;break ;} addOperand();exprFound=true;needOperand=false ;getToken(); break ; case Name : exprFound = true ;needOperand=false;getToken(); if(getTokenType() == Lparen ) bb1=addFunction(lTc1); else addName(lTc1) ; break ; case Lparen :recursiveLparen() ;break ; case Rparen :if(seeUnary) {errorUnary(lTc2 , 2);bb1 = false ;break ;} break ; default :if(needOperand) errorFactor(); bb1 = false ; break ; } if(seeUnary && bb1) addOperator(lTc2); return bb1 ; }
/// fa+b,c+d) /// f is the name of function // one error not checked f(a,,b) bool parserCls::addFunction(tokenContainCls &lTc1) { lTc1.type = FunctionName; addOperand(lTc1);bool bb2 = true ; bool bb3=false;EtokenType lt1;int iiExpr12=0,indexX=noTokenInExpr++; addOperand(lTc1); // for stack for change after end do{ if(bb3) addOperand(); else bb3 = true ; getToken();// get next token after ( if(!term1() ){ bb2 = false ;break ;} if((noTokenInExpr-2) > (indexX)) iiExpr12++; lt1= getTokenType(); }while((lt1==Comma)); if(bb2) if(lt1 != Rparen) {bb2 = false; errorRecursLparen(1, lTc1);} else {addOperator();getToken();} tokenContainCls lTc2(iiExpr12,1); addOperator(indexX, lTc2); return bb2 ; }
bool parserCls::factor(void) { EtokenType lTt1 = getTokenType(); bool bb1 = true ; tokenContainCls lTc1 =getCurToken(); switch(lTt1) { case OrdNumber: case SciNumber: case String : case Array : addOperand() ; exprFound = true ; needOperand = false ; noTokenInExpr++; getToken(); break ; case Name : exprFound = true ; needOperand = false ; noTokenInExpr++; getToken(); if(getTokenType() == Lparen ) addFunction(lTc1); else addName(lTc1) ; break ; case Lparen : addOperator() ; recursiveLparen() ; break ; case Rparen : break ; default : if(needOperand) errorFactor(); bb1 = false ; } return bb1 ; }
/* Function that lists and creates a cross reference table for the input file and writes the result to the output file. Works larkely like createCrossReferenceTable() but prints out the original line with a line number if it is a valid mal statement. This only happens if there the line starts with a comment, a label or if there exists an opcode. It is assumed that the input file is a valid .mal file. The function uses strtok to discern which section of the file it is in. Based on this the function will either store an identifier - as a label or an operand, or it will try and find a different operand, or do the same for a new line. @inputFile The file to be read @outputFile the output file to write the result */ void list_AND_CreateTable(FILE **inputFile, FILE **outputFile) { // Declares variable to store the line number int lineNumber; // Declares the head and the tail of the labelNode list, and current to move through it LABELNODE *head, *tail, *current; // Declares a current opNode to move through the list of occurances of an identifier OPNODE *currentOp; // Declares pointers to the original line read in, and a copy of it to be worked with char *line, *tempLine; // Allocates memory for the original line if( (line = (char *)malloc(LINE_LENGTH * sizeof(char))) == NULL) { // Prints error message if memory could not be alocated fprintf(stderr, "Could not allocate memory\n"); // Exits the programme exit(1); } // Sets head and tail of labelNode list to NULL. The list is empty head = tail = NULL; // Sets the line number to be one lineNumber = 1; // Loop that all the lines from the input file. while( fgets(line, LINE_LENGTH, *inputFile) != NULL) { // Initializes and resets tempLine to be NULL for further iterations tempLine = NULL; // Allocates memory for the temporary line if( (tempLine = (char *)malloc(LINE_LENGTH * sizeof(char))) == NULL) { // Prints error message if memory could not be alocated fprintf(stderr, "Could not allocate memory\n"); // Exits the programme exit(1); } // Copies the original line into the temporary one strcpy(tempLine, line); // Cheks if the first char is a comment, and is to be ignored if(tempLine[0] == '#') { // Increments the line number after printing the original line with a line number fprintf(*outputFile, "#%d %s", lineNumber++, line); // Starts the new iteration of the loop. Reads the next line from the file continue; } // Checks if the first char is a whitespace. No label is defined, but an opcode could occur else if(tempLine[0] == ' ' || tempLine[0] == '\t' || tempLine[0] == '\n') { // Remove whitespace to get to the opCode, or the end of the line. tempLine = strtok(tempLine, " \t"); }// If not any of the above, there is a label to be defined else { // Tokenize the label by replacing the : delimenating the label tempLine = strtok(tempLine, ":"); // The the label to the list addLabel(tempLine, lineNumber, &head, &tail); // Remove the white space between the label and the opCode tempLine = strtok(NULL, " \t"); } // Checks if there is no opCode to be found if(tempLine == NULL || *tempLine == '\n') { // Prints the blank original line with no line number fprintf(*outputFile, "%s", line); // Starts the new iteration of the loop. Reads the next line from the file continue; } // If there was an opCode else if(tempLine != NULL || tempLine[0] != '\n') { // Writes the original line with a line number, because it has an opcode, and thus is a valid statement fprintf(*outputFile, "#%d %s", lineNumber, line); // Ignore the opCode, by moving to the operand field of the line. Removes the white space before it. tempLine = strtok(NULL, " ,\t\n"); // Checks if the current section is a comment. No operands were found if(tempLine != NULL && tempLine[0] == '#') { // Increment the line number lineNumber++; // Starts the new iteration of the loop. Reads the next line from the file continue; } // Checks if the line starts with a newline char else if(tempLine != NULL && tempLine[0] == '\n') { // Starts the new iteration of the loop. Reads the next line from the file continue; } // There are operands to check else { // Loop that goes through all the oprands by checking that the line does not start with # or \n. while(tempLine != NULL && *tempLine != '#' && *tempLine != '\n') { // Checks if the operand is a valid identifier if( isalpha(*tempLine) != 0 || *tempLine == '_') { // Add the identifier as an operand addOperand(tempLine, lineNumber, &head, &tail); // Set the line to start at the next operand, comment or end of the line tempLine = strtok(NULL, ", \t\n"); } // Checks if the operand starts with a double or single quote else if(*tempLine == '\'' || *tempLine == '"') { // Stops the loop as there is nothing more to check for. No identifiers can occur at this point. break; } // If the operand is to be ignored else { // Move to the next operand, comment or end of the line. tempLine = strtok(NULL, " ,\t\n"); } } } // Increments the line number lineNumber++; } } // *** Writes the result of the parsing to the output file. *** // Sets current to be head. current = head; // Sets currentOp to NULL. currentOp = NULL; // Writes the headers for the table fprintf(*outputFile, "\n Cross Reference Table\n\n\tIdentifier \tDefinition \tUse\n\n"); // Flushses the memory buffer fflush(*outputFile); // If there are no labels to create a table from if(head == NULL) { fprintf(*outputFile, "\t *** Table is empty ***\n"); // Flushes the memory buffer fflush(*outputFile); } // If there are nodes to create a table from else { // Loop that goes through all the nodes in the list while(current != NULL) { if(strlen(current->identifier) > TAB) { fprintf(*outputFile, "\t %s \t %d \t\t ", current->identifier, current->defined); // Flushes the memory buffer fflush(*outputFile); } else { fprintf(*outputFile, "\t %s \t\t %d \t\t ", current->identifier, current->defined); // Flushes the memory buffer fflush(*outputFile); } // Sets the currentOp to be that of this labelNode's head currentOp = current->head; // Loop that goes through all the opNodes for this labelNode while(currentOp != NULL) { // Writes the line where the label was used fprintf(*outputFile, "%d ", currentOp->used); // Flushes the memory buffer fflush(*outputFile); // Moves to the next node in the list currentOp = currentOp->next; } // Writes a newline char when the current label is done fprintf(*outputFile, "\n"); // Flushes the memory buffer fflush(*outputFile); // Moves to the next node current = current->next; } } // Closes the input file fclose(*inputFile); // Closes the output file fclose(*outputFile); }
void addOperand(const char* base, Args&&... args) { addOperand(std::make_shared<Translateable>(base, args...)); }