|  | @@ -85,18 +85,26 @@ export class IVProgParser {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  checkOpenCurly () {
 | 
	
		
			
				|  |  | +  checkOpenCurly (attempt = false) {
 | 
	
		
			
				|  |  |      const token = this.getToken();
 | 
	
		
			
				|  |  |      if(this.lexerClass.OPEN_CURLY !== token.type){
 | 
	
		
			
				|  |  | -      throw SyntaxError.createError('{', token);
 | 
	
		
			
				|  |  | +      if(!attempt)
 | 
	
		
			
				|  |  | +        throw SyntaxError.createError('{', token);
 | 
	
		
			
				|  |  | +      else
 | 
	
		
			
				|  |  | +        return false;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +    return true;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  checkCloseCurly () {
 | 
	
		
			
				|  |  | +  checkCloseCurly (attempt = false) {
 | 
	
		
			
				|  |  |      const token = this.getToken();
 | 
	
		
			
				|  |  |      if(this.lexerClass.CLOSE_CURLY !== token.type){
 | 
	
		
			
				|  |  | -      throw SyntaxError.createError('}', token);
 | 
	
		
			
				|  |  | +      if(!attempt)
 | 
	
		
			
				|  |  | +        throw SyntaxError.createError('}', token);
 | 
	
		
			
				|  |  | +      else
 | 
	
		
			
				|  |  | +        return false;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +    return true;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /* It checks if the current token at position pos is a ']'.
 | 
	
	
		
			
				|  | @@ -457,59 +465,76 @@ export class IVProgParser {
 | 
	
		
			
				|  |  |      throw SyntaxError.createError(this.getTypesAsString(scope), token);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  parseCommandBlock (scope = IVProgParser.FUNCTION) {
 | 
	
		
			
				|  |  | +  parseCommandBlock (scope = IVProgParser.FUNCTION, optionalCurly = false) {
 | 
	
		
			
				|  |  |      let variablesDecl = [];
 | 
	
		
			
				|  |  |      const commands = [];
 | 
	
		
			
				|  |  | -    this.checkOpenCurly();
 | 
	
		
			
				|  |  | -    this.pos++;
 | 
	
		
			
				|  |  | +    let hasOpen = false;
 | 
	
		
			
				|  |  | +    if (this.checkOpenCurly(optionalCurly)) {
 | 
	
		
			
				|  |  | +      this.pos++;
 | 
	
		
			
				|  |  | +      hasOpen = true;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |      this.consumeNewLines();
 | 
	
		
			
				|  |  |      while(true) {
 | 
	
		
			
				|  |  | -      const token = this.getToken();
 | 
	
		
			
				|  |  | -      let cmd = null;
 | 
	
		
			
				|  |  | -      if (this.isVariableType(token)) {
 | 
	
		
			
				|  |  | -        if(scope !== IVProgParser.FUNCTION) {
 | 
	
		
			
				|  |  | -          // TODO better error message
 | 
	
		
			
				|  |  | -          throw new Error(`Cannot declare variable here (line ${token.line})`);
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        this.pos++;
 | 
	
		
			
				|  |  | -        variablesDecl = variablesDecl.concat(this.parseDeclararion(token));
 | 
	
		
			
				|  |  | -        this.checkEOS();
 | 
	
		
			
				|  |  | -        this.pos++;
 | 
	
		
			
				|  |  | -        cmd = -1;
 | 
	
		
			
				|  |  | -      } else if (token.type === this.lexerClass.ID) {
 | 
	
		
			
				|  |  | -        cmd = this.parseIDCommand();
 | 
	
		
			
				|  |  | -      } else if (token.type === this.lexerClass.RK_RETURN) {
 | 
	
		
			
				|  |  | -        cmd = this.parseReturn();
 | 
	
		
			
				|  |  | -      } else if (token.type === this.lexerClass.RK_WHILE) {
 | 
	
		
			
				|  |  | -        cmd = this.parseWhile();
 | 
	
		
			
				|  |  | -      } else if (token.type === this.lexerClass.RK_FOR) {
 | 
	
		
			
				|  |  | -        cmd = this.parseFor();
 | 
	
		
			
				|  |  | -      } else if (token.type === this.lexerClass.RK_BREAK ) {
 | 
	
		
			
				|  |  | -        if(scope !== IVProgParser.BREAKABLE) {
 | 
	
		
			
				|  |  | -          // TODO better error message
 | 
	
		
			
				|  |  | -          throw new Error("Break cannot be used outside of a loop.");
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        cmd = this.parseBreak();
 | 
	
		
			
				|  |  | -      } else if (token.type === this.lexerClass.RK_SWITCH) {
 | 
	
		
			
				|  |  | -        cmd = this.parseSwitchCase();
 | 
	
		
			
				|  |  | -      } else if (token.type === this.lexerClass.RK_DO) {
 | 
	
		
			
				|  |  | -        cmd = this.parseDoWhile();
 | 
	
		
			
				|  |  | -      } else if (token.type === this.lexerClass.RK_IF) {
 | 
	
		
			
				|  |  | -        cmd = this.parseIfThenElse();
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +      const cmd = this.parseCommand(scope);
 | 
	
		
			
				|  |  |        if (cmd === null)
 | 
	
		
			
				|  |  |          break;
 | 
	
		
			
				|  |  | -      if(cmd !== -1)
 | 
	
		
			
				|  |  | -        commands.push(cmd);
 | 
	
		
			
				|  |  | +      if(cmd !== -1) {
 | 
	
		
			
				|  |  | +        if (cmd instanceof Commands.Declaration) {
 | 
	
		
			
				|  |  | +          variablesDecl.push(cmd);
 | 
	
		
			
				|  |  | +        } else {
 | 
	
		
			
				|  |  | +          commands.push(cmd);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      this.consumeNewLines();
 | 
	
		
			
				|  |  | -    this.checkCloseCurly();
 | 
	
		
			
				|  |  | -    this.pos++;
 | 
	
		
			
				|  |  | -    this.consumeNewLines();
 | 
	
		
			
				|  |  | +    if (hasOpen) {
 | 
	
		
			
				|  |  | +      this.checkCloseCurly()
 | 
	
		
			
				|  |  | +      this.pos++;
 | 
	
		
			
				|  |  | +      this.consumeNewLines();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |      return new Commands.CommandBlock(variablesDecl, commands);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +  parseCommand (scope) {
 | 
	
		
			
				|  |  | +    const token = this.getToken();
 | 
	
		
			
				|  |  | +    let cmd = null;
 | 
	
		
			
				|  |  | +    if (this.isVariableType(token)) {
 | 
	
		
			
				|  |  | +      if(scope !== IVProgParser.FUNCTION) {
 | 
	
		
			
				|  |  | +        // TODO better error message
 | 
	
		
			
				|  |  | +        throw new Error(`Cannot declare variable here (line ${token.line})`);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      this.pos++;
 | 
	
		
			
				|  |  | +      cmd = this.parseDeclararion(token);
 | 
	
		
			
				|  |  | +      this.checkEOS();
 | 
	
		
			
				|  |  | +      this.pos++;
 | 
	
		
			
				|  |  | +    } else if (token.type === this.lexerClass.ID) {
 | 
	
		
			
				|  |  | +      cmd = this.parseIDCommand();
 | 
	
		
			
				|  |  | +    } else if (token.type === this.lexerClass.RK_RETURN) {
 | 
	
		
			
				|  |  | +      cmd = this.parseReturn();
 | 
	
		
			
				|  |  | +    } else if (token.type === this.lexerClass.RK_WHILE) {
 | 
	
		
			
				|  |  | +      cmd = this.parseWhile();
 | 
	
		
			
				|  |  | +    } else if (token.type === this.lexerClass.RK_FOR) {
 | 
	
		
			
				|  |  | +      cmd = this.parseFor();
 | 
	
		
			
				|  |  | +    } else if (token.type === this.lexerClass.RK_BREAK ) {
 | 
	
		
			
				|  |  | +      if(scope !== IVProgParser.BREAKABLE) {
 | 
	
		
			
				|  |  | +        // TODO better error message
 | 
	
		
			
				|  |  | +        throw new Error("Break cannot be used outside of a loop.");
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      cmd = this.parseBreak();
 | 
	
		
			
				|  |  | +    } else if (token.type === this.lexerClass.RK_SWITCH) {
 | 
	
		
			
				|  |  | +      cmd = this.parseSwitchCase();
 | 
	
		
			
				|  |  | +    } else if (token.type === this.lexerClass.RK_DO) {
 | 
	
		
			
				|  |  | +      cmd = this.parseDoWhile();
 | 
	
		
			
				|  |  | +    } else if (token.type === this.lexerClass.RK_IF) {
 | 
	
		
			
				|  |  | +      cmd = this.parseIfThenElse();
 | 
	
		
			
				|  |  | +    } else if (this.checkEOS(true)){
 | 
	
		
			
				|  |  | +      this.pos++;
 | 
	
		
			
				|  |  | +      cmd = -1;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    return cmd;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    parseSwitchCase () {
 | 
	
		
			
				|  |  |      this.pos++;
 | 
	
		
			
				|  |  |      this.checkOpenParenthesis();
 | 
	
	
		
			
				|  | @@ -533,7 +558,7 @@ export class IVProgParser {
 | 
	
		
			
				|  |  |    parseDoWhile () {
 | 
	
		
			
				|  |  |      this.pos++;
 | 
	
		
			
				|  |  |      this.consumeNewLines();
 | 
	
		
			
				|  |  | -    const commandsBlock = this.parseCommandBlock();
 | 
	
		
			
				|  |  | +    const commandsBlock = this.parseCommandBlock(IVProgParser.BREAKABLE);
 | 
	
		
			
				|  |  |      this.consumeNewLines(); //Maybe not...
 | 
	
		
			
				|  |  |      const whileToken = this.getToken();
 | 
	
		
			
				|  |  |      if (whileToken !== this.lexerClass.RK_WHILE) {
 | 
	
	
		
			
				|  | @@ -666,6 +691,14 @@ export class IVProgParser {
 | 
	
		
			
				|  |  |      return new Commands.Assign(id, exp);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +  parseCases () {
 | 
	
		
			
				|  |  | +    const token = this.getToken();
 | 
	
		
			
				|  |  | +    if(token.type !== this.lexerClass.RK_CASE) {
 | 
	
		
			
				|  |  | +      throw SyntaxError.createError(this.lexer.literalNames[this.lexerClass.RK_CASE], token);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    /*
 | 
	
		
			
				|  |  |    * Parses an Expression following the structure:
 | 
	
		
			
				|  |  |    *
 |