/// Present a simple challenge consisting of two random digits to /// add. The user tries to enter the last digit of their sum. void askSum(MorseToken) { uint8_t a(getDigitByWeight()); uint8_t b(getDigitByWeight()); char buffer[3] = { char(a + '0'), char(b + '0'), 0 }; txString(buffer); pushSymbolStack(MorseToken(buffer[0], MorseToken::Char)); pushSymbolStack(MorseToken(buffer[1], MorseToken::Char)); saveActions(); for (size_t i('0'); i <= '9' ; ++i) { assignAction(MorseToken(i, MorseToken::Char), gradeRestore); } }
/// This is a little harder than askNext in that the extra letters can /// be distracting, but it is a little easier because there's more /// context. I expect that for beginners, the former is easier, but for /// intermediates, the latter is good practice. void askNextAlfa(MorseToken) { uint8_t a(random(26)); txAlfaBravoCharlie(MorseToken(a + 'A', MorseToken::Char)); uint8_t b((a + 1) % 26); pushSymbolStack(MorseToken(b + 'A', MorseToken::Char)); assignAction(MorseToken('I', MorseToken::Char), gradeNext); saveActions(); for (size_t i('A'); i <= 'Z' ; ++i) { assignAction(MorseToken(i, MorseToken::Char), push1RestoreAll); } }
/// Prompt with a random letter of the alphabet. The user enters the /// letter then enters I to get graded. void askNext(MorseToken) { uint8_t a(random(26)); char buffer[3] = { char(a + 'A'), 0 }; txString(buffer); uint8_t b((a + 1) % 26); pushSymbolStack(MorseToken(b + 'A', MorseToken::Char)); assignAction(MorseToken('I', MorseToken::Char), gradeNext); saveActions(); for (size_t i('A'); i <= 'Z' ; ++i) { assignAction(MorseToken(i, MorseToken::Char), push1RestoreAll); } }
void gradeRestore(MorseToken answer) { pushSymbolStack(answer); gradeSum(MorseToken()); restoreActions(); }
void semantics(ASTnode* ASTroot){ firstMatrix=1; if(ASTroot==NULL){ return; } int z,noTraverse=0; ASTnode *rows,*l; token bufToken; SymbolTable *tmp; SymbolTableEntryNode *t; int p=0; if(sflag==0){ //first time, main function so create a symbol table for main function sflag=1; S[0]=createSymbolTable(size, NULL, "MAIN");//parentTable of Main is NULL symbolStack=createSymbolStack(); pushSymbolStack(S[0],symbolStack); p=1; counter++; } switch(ASTroot->label){ //Symbol Table creates only in 1, 61, 64 //Symbol table populates in 1:functionDef,31:declarationStmt case 1://make a new symbol table, this would be the scope unless an END is encountered, functionDef InsertSymbolTable(topSymbolStack(symbolStack), ASTroot); S[counter]=createSymbolTable(size, topSymbolStack(symbolStack),ASTroot->array[1]->t.lexeme); pushSymbolStack(S[counter],symbolStack); InsertSymbolTableFun(topSymbolStack(symbolStack), ASTroot);//for input and output arguments of function p=1; counter++; break; case 2://ifstmt S[counter]=createSymbolTable(size, topSymbolStack(symbolStack),"IF"); pushSymbolStack(S[counter],symbolStack); p=1; counter++; break; case 3: noTraverse=1; if(strcmp(topSymbolStack(symbolStack)->symbolTableName,ASTroot->array[0]->t.lexeme)==0){//checking for Recursion semanticError(3,ASTroot->array[0]->t); return; } //check for input parameter list and function signature- input and output tmp=topSymbolStack(symbolStack); while(tmp!=NULL){ z=SearchHashTable(tmp, ASTroot->array[0]->t.lexeme); if(z!=-1) break; else tmp=tmp->parentTable; } if(tmp==NULL){ semanticError(1,ASTroot->t); break; }//declaration of FunId is checked here itself t=findSymbolTableNode(tmp->table[z].next,ASTroot->array[0]->t.lexeme); if(t->type.fid.outputSize!=typeCounter){ semanticError(5,ASTroot->array[0]->t); break; } else{ for(z=0; z<=t->type.fid.outputSize; z++){ if(t->type.fid.output[z]!=type[z]){ semanticError(5,ASTroot->array[0]->t); noTraverse=1; break;//from for } } typeCounter=-1;//successfully implemented. } l=ASTroot->array[1]; for(z=0; z<=t->type.fid.inputSize; z++){ if(l==NULL){ semanticError(5,ASTroot->array[0]->t);//number of output parameters noTraverse=1; break; } if(t->type.fid.input[z]!=findTypeVar(l->array[0])){ semanticError(14,ASTroot->array[0]->t);//type Mismatch noTraverse=1; break; } l=l->array[1]; } break; case 11://else stmt S[counter]=createSymbolTable(size, topSymbolStack(symbolStack),"ELSE"); pushSymbolStack(S[counter],symbolStack); p=1; counter++; break; case 26:if(ASTroot->array[0]->label==67){ t=getSymbolTableNode(ASTroot->array[1]); t->type.id.initialized=1; } case 27: break; case 28: break; //it should not come case 29: break; case 30: break; case 31://declaration stmt InsertSymbolTable(topSymbolStack(symbolStack), ASTroot); return; break; case 51://Assignment noTraverse=1; typeCounter=-1; if(ASTroot->array[1]->label==3){//function call statement if(ASTroot->array[0]->label==54){//single list if(outputCheck1(ASTroot->array[0])==0)//send leaf directly return; //1- it should already have been declared, 2-if so, then it's type should be recorded } else{ //send l if(outputCheck(ASTroot->array[0])==0) return; } semantics(ASTroot->array[1]); } if(ASTroot->array[1]->label==60){//size stmt //1- check if ID is declared, 2- What is the type of ID, 3- Compare with the return type if(!isDeclared(ASTroot->array[1]->array[0])){ semanticError(1,ASTroot->array[1]->array[0]->t); return; } z=findType(ASTroot->array[1]->array[0],0); if(z==57){ if(outputCheck(ASTroot->array[0])==0){//it will populate type of LHS if declared, else returns 0 return; } else{//declared if(!(typeCounter==0&&type[0]==57)) semanticError(6,ASTroot->array[0]->t); return; } } else if(z==58){ if(outputCheck(ASTroot->array[0])==0){//it will populate type of LHS if declared, else returns 0 return; } else{//declared if(!(typeCounter==1&&type[0]==55&&type[1]==55)) semanticError(6,ASTroot->array[0]->t); return; } } else { semanticError(8,ASTroot->array[1]->array[0]->t);//Size contains other that String and Matrix } } if(ASTroot->array[1]->label==37){//Arithmetic Expression l=ASTroot->array[0]; z=findType(l,1); if(l->label==54){ if(z==57){ if(ASTroot->array[1]->array[1]==NULL){ if(ASTroot->array[1]->array[0]->array[1]==NULL){ if(findTypeVar(ASTroot->array[1]->array[0]->array[0])==57){//initialization StringInit(ASTroot->array[0],ASTroot->array[1]->array[0]->array[0]->t.lexeme); return; } } } } else if(z==58){//lhs is matrix firstMatrix=1; if(ASTroot->array[1]->array[1]==NULL){ if(ASTroot->array[1]->array[0]->array[1]==NULL){ if((ASTroot->array[1]->array[0]->array[0]->label)==44){//initialization MatrixInit(ASTroot->array[0],ASTroot->array[1]->array[0]->array[0]); return; } } } } } if(z==-1) break; typeCounter++; type[typeCounter]=z; if((z=findTypeAE(ASTroot->array[1]))!=type[typeCounter]){ bufToken.lineNumber=l->t.lineNumber; semanticError(10,bufToken); break; } //valid Arithmetic expression //debug(); t= getSymbolTableNode(ASTroot->array[0]); t->type.id.initialized=1; typeCounter=-1; } break; case 52://go to case 54 case 54: if(!isDeclared(ASTroot)) semanticError(1,ASTroot->t); break; case 75:// AND case 76:// OR case 77:// LT case 78:// LE case 79:// EQ case 80:// GT case 81:// GE case 82:// NE case 83:// NOTbooleanExpressionSemantics(ASTnode* BE) noTraverse=1; if(booleanExpressionSemantics(ASTroot)==0){ semanticError(10,bufToken); } default: break; }//end of switch int i; if(noTraverse==0){ for( i=0; i<ASTroot->arraySize; i++){ if(ASTroot->array[i]!=NULL){ semantics(ASTroot->array[i]); } } } if(p){ //if popping SymbolTable is a function, then check if it's output parameter are accurately initialised or not tmp=popSymbolStack(symbolStack); if(strcmp(tmp->symbolTableName,"MAIN")!=0&&strcmp(tmp->symbolTableName,"IF")!=0&&strcmp(tmp->symbolTableName,"ELSE")!=0){//it is a function int i; for(i=0; i<tmp->outputParameter; i++){ t=outputParameterInitCheck(tmp,tmp->outputParameterLexeme[i]); if(t->type.id.initialized!=1) { semanticError(13,ASTroot->array[1]->t); break; } } } } }//end of function