/** * This function tests if a given line (split into tokens) has the right components * to be registering a new variable. */ bool isRegisteringVariable(MavenCompiler* c, StringList tokens) { // what does it take to register a variable? // 1. must have a datatype. // 2. must not have brackets (). // 3. is allowed to have a default value, but be careful where its placed. // this function needs to be improved to work like dissectFunction() // skip other keywords int token; for(token = 0; token < tokens.length(); ++token) if(tokens[token] != "public" && tokens[token] != "private" && tokens[token] != "static" && tokens[token] != "constant" && tokens[token] != "constant" && tokens[token] != "writeonly") break; // check data type string rawtype = stripRawType(tokens[token]); if(!isDataType(rawtype) && !objectExists(c, rawtype) && !enumExists(c, rawtype)) return false; // the rest for(int i = 0; i < tokens.length(); ++i) { for(int j = 0; j < tokens[i].length(); ++j) { if(tokens[i][j] == '=') return true; if(tokens[i][j] == '(' || tokens[i][j] == ')') return false; } } return true; }
/* * 简单判断是否是变量定义,只是判断开始是否为数据类型 */ bool isVariableDef(char * buf){ skipSpace(&buf); if(isDataType(buf) == true){ return true; } return false; }
MavenVariable dissectVariable(MavenCompiler* c, string line) { MavenVariable v; StringList parts = smartTokens(line); v.atLine = c->lineNumber; // variable length arguments if(trim(line) == "...") { v.type = "maven.Object[]"; v.name = "varargs"; return v; } // read keywords in order if(trim(line) == "") return v; int i = 0; if(parts[i] == "public") { v.isPublic = true; ++i; } else if(parts[i] == "private") { v.isPublic = false; ++i; } if(parts[i] == "constant") { v.mutability = MU_CONSTANT; ++i; } if(parts[i] == "static") { v.isStatic = true; ++i; } v.type = parts[i++]; int nID = findNamespaceID(c, c->currentNamespace); smartAssert(nID >= 0); int enumID = findEnumID(c, nID, v.type); if(!isDataType(v.type) && enumID < 0) v.type = findMavenObjectPath(c, v.type); if(enumID >= 0) v.type = c->currentNamespace + "." + c->namespaces->at(nID).enums[enumID].name; v.name = parts[i++]; return v; }
string keywordNew(MavenCompiler* c, string entity, string element, string args, string& type) { string rawType = stripRawType(entity); int depth = ((element != "") ? 1 : 0); //cout << "entity = '" << entity << "', element = '" << element << "', args = '" << args << "', line = " << c->lineNumber << endl; // if this is a native type StringList types; MavenMutability mut; if(isDataType(rawType)) { type = appendArrayDepth(c, rawType, depth); string r = "new maven::" + rawType + "Array(" + dissectCode(c, element, types, mut) + ")"; // bug #54: make sure types is 'int' return r; } // first make sure the class exists bool isEnum = false; type = appendArrayDepth(c, findMavenObjectPath(c, trim(entity)), depth); if(stripRawType(type) == MAVEN_INVALID) { if(enumExists(c, stripRawType(entity))) { isEnum = true; type = c->currentNamespace + "." + appendArrayDepth(c, entity, depth); } else { pushError(c, "Unknown class '%s'", stripRawType(type)); return MAVEN_INVALID; } } int namespaceID, objectID; findClass(c, entity, namespaceID, objectID); smartAssert(namespaceID >= 0); smartAssert(objectID >= 0); // if its a single Object if(element == "") { string r = "new "; r += c->namespaces->at(namespaceID).name + "::" + c->namespaces->at(namespaceID).objects->at(objectID)->name; for(int i = 0; i < depth; ++i) r += "*"; // args is assumed to be predissected. return r + "(" + args + ")"; } else { string elements = dissectCode(c, element, types, mut); // bug #54: make sure types is 'int' string r = "new maven::"; if(isEnum) { r += "int"; rawType = "int"; int nID = findNamespaceID(c, c->currentNamespace); smartAssert(nID >= 0); int enumID = findEnumID(c, nID, entity); smartAssert(enumID >= 0); if(trim(args) == "") args = intToString(c->namespaces->at(nID).enums[enumID].getDefaultValue()); } else r += "object"; string tempVar = getNextTempVariable(c); if(isDataType(rawType)) c->beforeLine += rawType + "* " + tempVar + " = new " + rawType + "[" + elements + "];\n"; else c->beforeLine += "maven::Object** " + tempVar + " = new maven::Object*[" + elements + "];\n"; c->beforeLine += "for(int __INIT = 0; __INIT < " + elements + "; ++__INIT)\n"; if(isDataType(rawType)) { if(trim(args) == "") args = "0"; c->beforeLine += tempVar + "[__INIT] = " + args + ";\n"; } else c->beforeLine += tempVar + "[__INIT] = (maven::Object*) new " + rawType + "(" + args + ");\n"; r += "Array(" + elements + "," + tempVar + ")"; return r; } }
int main(){ freopen("lexer_output.txt", "r", stdin); trieRoot = createNewTrieNode(); if(trieRoot == NULL){ perror("Could not create root node!!\n"); return 0; } envTop = NULL; currentScope = totalVariables = 0; addScope(); token t; while(scanf("%d%d", &t.iden, &t.line) != EOF){ fgets(t.value, 1000, stdin); int len = strlen(t.value); t.value[len-1] = '\0'; if(t.value[0] == '-') t.value[0] = '\0'; t.line++; lexemeStream[stream_size++] = t; } // int zz; // for(zz=0;zz<stream_size;zz++) // printf("%d ", lexemeStream[zz].iden); printf("\n"); int i, n = stream_size, lastLineOfDeclaration = -1, lastDataTypeOfDeclaration = -1; int lastDataTypeOfAssignment = -1, lastLineOfAssignment = -1; funcName[0] = '!'; funcName[1] = '\0'; int insideMain = 0, diff = 0; funcParameterCount = 0; for(i=0;i<n;i++){ if(lexemeStream[i].iden == MAIN) insideMain = 1; if(i == 2){ if(lexemeStream[i].iden != MAIN){ assert(lexemeStream[i].iden == FUNC); strcpy(funcName, lexemeStream[i+1].value); } i++; continue; } //check for recursive function calls if(lexemeStream[i].iden == FUNC && !insideMain){ printf("Semantic error: Recursive function calls not allowed.\n"); continue; } if(lexemeStream[i].iden == LSQ){ diff++; continue; } if(lexemeStream[i].iden == RSQ){ diff--; continue; } //store function parameter list if(isDataType(lexemeStream[i].iden) && diff > 0 && !insideMain){ funcParameterType[funcParameterCount++] = lexemeStream[i].iden; } //for function calls inside main, check whether correct function name is used //then check for correct number and types of parameters if(insideMain && i > 0 && lexemeStream[i].iden == IDEN && lexemeStream[i-1].iden == FUNC){ if(strcmp(funcName, lexemeStream[i].value) > 0) printf("Function named %s in line %d not declared.\n", lexemeStream[i].value, lexemeStream[i].line); int j, argumentCount = 0, wrongType = 0; for(j=i+1;j < stream_size && lexemeStream[j].iden != RSQ;j++){ if(lexemeStream[j].iden != IDEN) continue; if(argumentCount < funcParameterCount && getDataType(lexemeStream[j]) != funcParameterType[argumentCount]) wrongType = lexemeStream[j].line; argumentCount++; } if(argumentCount != funcParameterCount) printf("Incorrect number of function arguments in line %d.\n", lexemeStream[j].line); if(wrongType > 0) printf("Type mismatch in function parameters in line %d.\n", wrongType); i = j; continue; } if(lexemeStream[i].iden == LAD){ addScope(); continue; } if(lexemeStream[i].iden == RAD){ deleteScope(); continue; } if(isDataType(lexemeStream[i].iden)){ lastLineOfDeclaration = lexemeStream[i].line; lastDataTypeOfDeclaration = lexemeStream[i].iden; // printf("setting lastlineOfDeclaration = %d because of %d.\n", lastLineOfDeclaration, lexemeStream[i].iden); continue; } if(lexemeStream[i].iden == ASSIGN){ //line number of assignment operator lastLineOfAssignment = lexemeStream[i].line; continue; } if(lexemeStream[i].iden == IDEN){ insert(lexemeStream[i].value); //check if variable is being declared or referenced if(lastLineOfDeclaration == lexemeStream[i].line){ //declared declareVariable(lexemeStream[i], lastDataTypeOfDeclaration); continue; } //referenced referenceVariable(lexemeStream[i]); if(lexemeStream[i].line != lastLineOfAssignment){ lastDataTypeOfAssignment = getDataType(lexemeStream[i]); continue; } if(lexemeStream[i].line == lastLineOfAssignment){ int dataType = getDataType(lexemeStream[i]); if(dataType != lastDataTypeOfAssignment){ printf("Semantic error in line %d: Type mismatch between LHS and RHS in line %d.\n", lexemeStream[i].line, lastLineOfAssignment); } continue; } } } // int c = 0, cc = 0; // EnvStackNode temp = envTop; // while(temp != NULL){ // c++; // EnvListNode ev = temp->ev; // while(ev != NULL){ // cc++; // ev = ev->next; // } // temp = temp->next; // } // printf("Total active scopes : %d and active variables = %d.\n", c, cc); // printf("\ncheck variable stack of size = %d :\n", z); // for(int i=0;i<z;i++){ // int idx = vvv[i]; // if(variableStack[idx] == NULL){ // printf("empty stack at idx = %d\n", idx); // continue; // } // printf("idx = %d has the value = %s\n", idx, variableStack[idx]->node.name); // } return 0; }