Exemple #1
0
void CParser::InitSymbolTable(CSymtab *s)
{
  CTypeManager *tm = CTypeManager::Get();
  
  // predefined functions:
  //  - DIM(a: ptr to array; dim: integer): integer
  //  - DOFS(a: ptr to array): integer
  //  - ReadInt(): integer
  //  - WriteInt(i:integer): void
  //  - WriteChar(c:char): void
  //  - WriteStr(str: char[]): void
  //  - WriteLn():void

  //  - DIM(a: ptr to array; dim: integer): integer
  CSymProc *DIM = new CSymProc("DIM", tm->GetInt());
  CSymParam *DIM_a = new CSymParam(0, "a", tm->GetPointer(tm->GetNull()));
  CSymParam *DIM_dim = new CSymParam(1, "dim", tm->GetInt());
  DIM->AddParam(DIM_a);
  DIM->AddParam(DIM_dim);
  s->AddSymbol(DIM);

  //  - DOFS(a: ptr to array): integer
  CSymProc *DOFS = new CSymProc("DOFS", tm->GetInt());
  CSymParam *DOFS_a = new CSymParam(0, "a", tm->GetPointer(tm->GetNull()));
  DOFS->AddParam(DOFS_a);
  s->AddSymbol(DOFS);

  //  - ReadInt(): integer
  CSymProc *ReadInt = new CSymProc("ReadInt", tm->GetInt());
  s->AddSymbol(ReadInt);
  
  //  - WriteInt(i:integer): void
  CSymProc *WriteInt = new CSymProc("WriteInt", tm->GetNull());
  CSymParam *WriteInt_i = new CSymParam(0, "i", tm->GetInt());
  WriteInt->AddParam(WriteInt_i);
  s->AddSymbol(WriteInt);

  //  - WriteChar(c:char): void
  CSymProc *WriteChar = new CSymProc("WriteChar", tm->GetNull());
  CSymParam *WriteChar_c = new CSymParam(0, "c", tm->GetChar());
  WriteChar->AddParam(WriteChar_c);
  s->AddSymbol(WriteChar);

  //  - WriteStr(str: char[]): void
  CSymProc *WriteStr = new CSymProc("WriteStr", tm->GetNull());
  CSymParam *WriteStr_str = new CSymParam(0, "str", tm->GetPointer(tm->GetArray(CArrayType::OPEN, tm->GetChar())));
  WriteStr->AddParam(WriteStr_str);
  s->AddSymbol(WriteStr);

  //  - WriteLn():void
  CSymProc *WriteLn = new CSymProc("WriteLn", tm->GetNull());
  s->AddSymbol(WriteLn);
}
Exemple #2
0
void CParser::InitSymbolTable(CSymtab *s)
{
  CTypeManager *tm = CTypeManager::Get();
  CSymProc *fun;

  // function DIM(array: pointer to array; dim: integer): integer
  fun = new CSymProc("DIM", tm->GetInt());
  fun->AddParam(new CSymParam(0, "arr", tm->GetPointer(tm->GetNull())));
  fun->AddParam(new CSymParam(1, "dim", tm->GetInt()));
  s->AddSymbol(fun);

  // function DOFS(array: pointer to array): integer;
  fun = new CSymProc("DOFS", tm->GetInt());
  fun->AddParam(new CSymParam(0, "arr", tm->GetPointer(tm->GetNull())));
  s->AddSymbol(fun);

  // function ReadInt() : integer;
  fun = new CSymProc("ReadInt", tm->GetInt());
  s->AddSymbol(fun);

  // procedure WriteInt(i: integer);
  fun = new CSymProc("WriteInt", tm->GetNull());
  fun->AddParam(new CSymParam(0, "i", tm->GetInt()));
  s->AddSymbol(fun);

  // procedure WriteChar(c: char);
  fun = new CSymProc("WriteChar", tm->GetNull());
  fun->AddParam(new CSymParam(0, "c", tm->GetChar()));
  s->AddSymbol(fun);

  // procedure WriteStr(string: char[]);
  fun = new CSymProc("WriteStr", tm->GetNull());
  fun->AddParam(new CSymParam(0, "str", tm->GetPointer(tm->GetArray(CArrayType::OPEN, tm->GetChar()))));
  s->AddSymbol(fun);

  // procedure WriteLn();
  fun = new CSymProc("WriteLn", tm->GetNull());
  s->AddSymbol(fun);
}
Exemple #3
0
void CParser::subroutineDecl(CAstScope *s) {
  //
  // subroutineDecl ::= (procedureDecl | functionDecl) subroutineBody ident ";".
  // procedureDecl ::= "procedure" ident [ formalParam ] ";".
  // functionDecl ::= "function" ident [ formalParam ] ":" type ";".
  // formalParam ::= "(" [ varDeclSequence ] ")".
  // subroutineBody ::= varDeclaration "begin" statSequence "end".
  // varDeclSequence ::= varDecl { ";" varDecl }.
  // varDecl ::= ident { "," ident } ":" type.
  //


  CToken subroutine_name;
  CToken subroutine_name_check;
  CTypeManager *tm = CTypeManager::Get();

  // procedureDecl
  if(_scanner->Peek().GetType() == tProcedure) {
    CToken t;
    CAstStatement *statseq = NULL;

    Consume(tProcedure);
    Consume(tIdent, &subroutine_name);
 
    // Check duplicate procedure declaration.
    if(dynamic_cast<CAstModule *>(s)) {
      if(s->GetSymbolTable()->FindSymbol(subroutine_name.GetValue(), sGlobal) != NULL)
        SetError(subroutine_name, "duplicate procedure/function declaration '" + subroutine_name.GetValue() + "'.");
    }
    else {
      if(s->GetSymbolTable()->FindSymbol(subroutine_name.GetValue(), sLocal) != NULL)
        SetError(subroutine_name, "duplicate procedure/function declaration '" + subroutine_name.GetValue() + "'.");
    }

    CSymProc *symproc = new CSymProc(subroutine_name.GetValue(), tm->GetNull());
    CAstProcedure *procedure = new CAstProcedure(subroutine_name, subroutine_name.GetValue(), s, symproc);

    // formalParam
    if(_scanner->Peek().GetType() == tLBrak) {
      Consume(tLBrak);

      if(_scanner->Peek().GetType() == tIdent) {
        varDeclParam(procedure, symproc, 0);

        while(1) {
          if(_scanner->Peek().GetType() == tSemicolon) {
            Consume(tSemicolon);
            varDeclParam(procedure, symproc, symproc->GetNParams());
          }
          else break;
        }
      }

      Consume(tRBrak);
    }
    
    s->GetSymbolTable()->AddSymbol(symproc);
    
    Consume(tSemicolon);

    // subroutineBody from here.
    // subroutineBody ::= varDeclaration "begin" statSequence "end".

    // varDeclaration
    if(_scanner->Peek().GetType() == tVar) {
      Consume(tVar);
      varDecl(procedure);
      Consume(tSemicolon);

      while(1) {
        if(_scanner->Peek().GetType() == tIdent) {
          varDecl(procedure);
          Consume(tSemicolon);
        }
        else break;
      }
    }

    Consume(tBegin);
    
    // statSequence
    statseq = statSequence(procedure);
    procedure->SetStatementSequence(statseq);

    Consume(tEnd);

    Consume(tIdent, &subroutine_name_check);
    
    // Check procedure names are equal.
    if(subroutine_name.GetValue() != subroutine_name_check.GetValue()) {
      SetError(subroutine_name_check, "procedure/function identifier mismatch ('" + subroutine_name.GetValue() + "' != '" + subroutine_name_check.GetValue() + "').");
    }

    Consume(tSemicolon);
  }
  // functionDecl
  else {
    CToken tmp;
    
    // Parameters are pushed into params. Then they will be added into symproc later.
    vector<CSymParam *> params;
    const CType *func_type;
    CAstStatement *statseq = NULL;
    
    Consume(tFunction);
    Consume(tIdent, &subroutine_name);

    // Check duplicate function declaration.
    if(dynamic_cast<CAstModule *>(s)) {
      if(s->GetSymbolTable()->FindSymbol(subroutine_name.GetValue(), sGlobal) != NULL)
        SetError(subroutine_name, "duplicate procedure/function declaration '" + subroutine_name.GetValue() + "'.");
    }
    else {
      if(s->GetSymbolTable()->FindSymbol(subroutine_name.GetValue(), sLocal) != NULL)
        SetError(subroutine_name, "duplicate procedure/function declaration '" + subroutine_name.GetValue() + "'.");
    }

    // formalParam
    if(_scanner->Peek().GetType() == tLBrak) {
      int idx = 0;
      CToken t;
      vector<string> vars;
      const CType *var_type;
      
      Consume(tLBrak);

      // Get parameters.
      if(_scanner->Peek().GetType() == tIdent) {                                                                              
        Consume(tIdent, &t);
        vars.push_back(t.GetValue());

        while(_scanner->Peek().GetType() == tComma) {
          Consume(tComma);
          Consume(tIdent, &t);

          // Check duplicate parameter declaration.
          for(int i = 0; i < vars.size(); i++) {
            if(vars[i] == t.GetValue()) {
              SetError(t, "duplicate variable declaration '" + t.GetValue() + "'.");
              break;
            }
          }

          vars.push_back(t.GetValue());
        }

        Consume(tColon);
        var_type = type(true);

        for(int i = vars.size() - 1; i >= 0; i--) {
          CSymParam *param = new CSymParam(i, vars[i], var_type);
          params.push_back(param);
          idx++;
        }

        // for multiple parameter declaration.
        while(1) {
          if(_scanner->Peek().GetType() == tSemicolon) {
            Consume(tSemicolon);

            CToken t_loop;
            vector<string> vars_loop;
            const CType *var_type_loop;

            Consume(tIdent, &t_loop);

            // Check duplicate parameter declaration.
            for(int i = 0; i < params.size(); i++) {
              if(params[i]->GetName() == t_loop.GetValue()) {
                SetError(t_loop, "duplicate variable declaration '" + t_loop.GetValue() + "'.");
                break;
              }
            }

            vars_loop.push_back(t_loop.GetValue());

            while(_scanner->Peek().GetType() == tComma) {
              Consume(tComma);
              Consume(tIdent, &t_loop);

              for(int i = 0; i < params.size(); i++) {
                if(params[i]->GetName() == t_loop.GetValue()) {
                  SetError(t_loop, "duplicate variable declaration '" + t_loop.GetValue() + "'.");
                  break;
                }
              }

              // Check duplicate parameter declaration.
              for(int i = 0; i < vars_loop.size(); i++) {
                if(vars_loop[i] == t_loop.GetValue()) {
                  SetError(t_loop, "duplicate variable declaration '" + t_loop.GetValue() + "'.");
                  break;
                }
              }

              vars_loop.push_back(t_loop.GetValue());
            }

            Consume(tColon);
            var_type_loop = type(true);
  
            int tmp_idx = idx;
            
            // Add parameters into vector 'params'.
            for(int i = vars_loop.size() - 1; i >= 0; i--) {
              CSymParam *param_loop = new CSymParam(i+tmp_idx, vars_loop[i], var_type_loop);
              params.push_back(param_loop);
              vars_loop.pop_back();
              idx++;
            }
          }
          else break;
        }
      }

      Consume(tRBrak);
    }

    Consume(tColon);
    func_type = type(false, true);
    Consume(tSemicolon);
    
    CSymProc *symproc = new CSymProc(subroutine_name.GetValue(), func_type);
    CAstProcedure *function = new CAstProcedure(subroutine_name, subroutine_name.GetValue(), s, symproc);
    
    assert(symproc != NULL);

    // Add parameters into symproc.
    for(int i = 0; i < params.size(); i++) {
      CSymParam *param = params[i];
      symproc->AddParam(param);
      function->GetSymbolTable()->AddSymbol(param);
    }

    while(!params.empty())
      params.pop_back();

    s->GetSymbolTable()->AddSymbol(symproc);
    
    // subroutineBody from here.
    // subroutineBody ::= varDeclaration "begin" statSequence "end".

    // varDeclaration
    if(_scanner->Peek().GetType() == tVar) {
      Consume(tVar);
      varDecl(function);
      Consume(tSemicolon);

      while(1) {
        if(_scanner->Peek().GetType() == tIdent) {
          varDecl(function);
          Consume(tSemicolon);
        }
        else break;
      }
    }

    Consume(tBegin);
    
    // statSequence
    statseq = statSequence(function);
    function->SetStatementSequence(statseq);

    Consume(tEnd);

    Consume(tIdent, &subroutine_name_check);
    
    // Check function names are equal.
    if(subroutine_name.GetValue() != subroutine_name_check.GetValue()) {
      SetError(subroutine_name_check, "procedure/function identifier mismatch ('" + subroutine_name.GetValue() + "' != '" + subroutine_name_check.GetValue() + "').");
    }

    Consume(tSemicolon);
  }
}