⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 identifierchecker.java

📁 java实现的一个pascal编译器
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/* File : IdentifierChecker.java
   Description: This class is belongs to one of the phases of the Semantic analyzer for 
   		JPascal, which checks that a variable, 
   		constant or process are declared only once. That there cannot be
   		a constant with the same name of a process or variable, and
   		vice versa.
   Author: Fidel Viegas (viegasfh@yahoo.com)
   Date: 12/02/1999
   Last Modification Date: 16/03/2000
*/
package uk.co.brainycreatures.jpascal.semantic;

import uk.co.brainycreatures.jpascal.analysis.*;
import uk.co.brainycreatures.jpascal.node.*;

import java.util.Hashtable;
import java.util.Vector;
import java.io.*;

/**
 * This class is the first stage of the Semantic Analysis phase. It checks that all the identifiers are declared 
 * only once and that they are declared before use. It also checks that the integer, real and character literals 
 * are not out of range.
 */
public class IdentifierChecker extends DepthFirstAdapter {
  /**
   * processes the storage of identifiers of a program and/or subprograms, monitors and processes.
   */
  private Hashtable global_table = new Hashtable();

  /**
   * stores the identifiers of a monitor.
   */
  private Hashtable monitor_table = new Hashtable();

  /**
   * set to true when a procedure or function are given arguments
   */
  private boolean throws_args = false;

  /**
   * used by previous_entity
   */
  private final short PROGRAM = 0;
 
  /**
   * set to true when a readln statement with arguments is
   * found.
   */
  private boolean readln_statement = false;

  /** 
   * used by previous_entity
   */
  private final short MONITOR = 1;

  /**
   * program or monitor
   */
   private short previous_entity = PROGRAM;

  /**
   * stores identifiers local to a function, procedure or process
   */
  private Hashtable local_table = new Hashtable();

  /**
   * Reports the error messages within a program.
    */
  private ErrorMessage err = new ErrorMessage();

  /**
   * Lets the Identifier Checker know that this is a program.  
   */
  private boolean program = true;

  /**
   * stores the procedures local to a monitor
   */
  private Hashtable monitor_procs = new Hashtable();

  /**
   * true if the entity is a monitor
   */
  private boolean monitor = false;

  /**
   * set to true if a monitor_call
   */
  private boolean monitor_call = false;

  /**
   * Stores the name of the current monitor, so that when declaring
   * procedures local to a monitor
   * can be checked against the monitor's name.
   */
  private String monitor_name;

  /**
   * Stores the name of the program
   */
  private String program_name;

  /**
   * Adds a new symbol table to the linked list
   * symbol_table.
   */
  public void caseAPresentProgramHeading(APresentProgramHeading node) {
    program_name = node.getIdentifier().getText();
  }

  /**
   * @see IdentifierChecker.caseAPresentProgramHeading
   */
  public void caseAEmptyProgramHeading(APresentProgramHeading node) {
    program_name = "Noname";
  }

  /**
   *  Checks if the new constant identifier being defined already exists. If it exists, then an error message
   * is reported. If it doesn't, then it is put in the symbol table of the current block(process, monitor, program,
   * subprogram.
   *
   * @parameter node This is the node representing a constant in the AST.
   */
  public void outAConstDeclaration(AConstDeclaration node){
    checkNewId(node.getIdentifier());
  }

  /**
   *  Checks if the constant identifier on the right hand side of the new constant being defined is
   * already defined.
   * @parameter node Represents the identifier of the constant on the right hand side of a const
   *                       constant declaration in the AST.
   */
  public void outASignedidentifierConstant(ASignedidentifierConstant node) {
    checkId(node.getIdentifier());
  }

  /**
   * @see IdentifierChecker.outASignedIdentifierConstant
   */
  public void outAIdentifierConstant(AIdentifierConstant node) {
    checkId(node.getIdentifier());
  }

  /**
   * If the identifier is from an export section, then put it in the export table
   * else, check if the identifier was already declared and report an error if it was.
   *
   * @param node Represents the node of the identifier being declared.
   */
  public void outASingleIdentifierList(ASingleIdentifierList node) {
    TIdentifier ident = node.getIdentifier();
    String key = ident.getText().toUpperCase();
    
    if (readln_statement || throws_args) {
      checkId(ident); // check if the identifier was declared
    }
    else {
      checkNewId(ident);
    }
  }

  /**
   * @see IdentifierChecker.outASingleIdentifierList
   */
  public void outASequenceIdentifierList(ASequenceIdentifierList node){
    TIdentifier ident = node.getIdentifier();
    String key = ident.getText().toUpperCase();

    if (readln_statement || throws_args) {
      checkId(ident); // check if the identifier was declared
    }
    else {
      checkNewId(ident);
    }
  }

  /**
   * checks if the identifier is already in the table and if it isn't
   * equal to a procedure, function, monitor or process if this is not
   * a program declaration.
   */
  public void outASimpleProcedureHeading(ASimpleProcedureHeading node) {
    checkProcedure(node.getIdentifier());
    if (!local_table.isEmpty()) {
      local_table.clear();
    }
  }
  
  /**
   * {simple_throws} procedure identifier semicolon throws identifierlist
   */
  public void inASimpleThrowsProcedureHeading(ASimpleThrowsProcedureHeading node) {
    checkProcedure(node.getIdentifier());
    if (!local_table.isEmpty()) {
      local_table.clear();
    }
    throws_args = true;
  }

  /**
   * out simple throws
   */
  public void outASimpleThrowsProcedureHeading(ASimpleThrowsProcedureHeading node) {
    throws_args = false;
  }

  /**
   * @see IdentifierChecker.outASimpleProcedureDeclarationHeading
   */
 public void inAArgumentsProcedureHeading(AArgumentsProcedureHeading node) {
    checkProcedure(node.getIdentifier());
    if (!local_table.isEmpty()) {
      local_table.clear(); 
    }
  }

  public void caseAArgumentsThrowsProcedureHeading(AArgumentsThrowsProcedureHeading node) {
    checkProcedure(node.getIdentifier());
    if (!local_table.isEmpty()) {
      local_table.clear(); 
    }
    if (node.getParameterList() != null) {
      node.getParameterList().apply(this);
    }

    throws_args = true;
    if (node.getIdentifierList() != null) {
      node.getIdentifierList().apply(this);
    }
    throws_args = false;
  }

  /**
   * @see IdentifierChecker.checkSubProgramHeading
   */
  public void outASimpleFunctionHeading(ASimpleFunctionHeading node) {
    checkFunction(node.getIdentifier());
    if (!local_table.isEmpty()) {
      local_table.clear();
    }
  }

  public void caseASimpleThrowsFunctionHeading(ASimpleThrowsFunctionHeading node) {
    checkFunction(node.getIdentifier());
    if (!local_table.isEmpty()) {
      local_table.clear();
    }

    throws_args = true;
    if (node.getIdentifierList() != null ) {
      node.getIdentifierList().apply(this);
    }
    throws_args = false;
  }

  /**
   * checks if the exceptions identifiers where previously declared
   */
  public void caseAArgumentsFunctionHeading(AArgumentsFunctionHeading node) {
    checkFunction(node.getIdentifier());
    if (!local_table.isEmpty()) {
      local_table.clear();
    }
    
    if (node.getParameterList() != null) {
      node.getParameterList().apply(this);
    }
  }

  /**
   * checks if the exceptions identifiers where previously declared
   */
  public void caseAArgumentsThrowsFunctionHeading(AArgumentsThrowsFunctionHeading node) {
    checkFunction(node.getIdentifier());
    if (!local_table.isEmpty()) {
      local_table.clear();
    }
    if (node.getParameterList() != null) {
      node.getParameterList().apply(this);
    }
    throws_args = true;
    if (node.getIdentifierList() != null) {
      node.getIdentifierList().apply(this);
    }
    throws_args = false;
  }

  /**
   * checks if the identifier already exists in the global table
   */
  public void outAMonitorHeading(AMonitorHeading node) {
    TIdentifier ident = node.getIdentifier();
    String key = ident.getText().toUpperCase();

    checkMonitor(ident);
    program = false;
    monitor = true;
    monitor_name = ident.getText();
    if (!monitor_table.isEmpty()) {
      monitor_table.clear();
    }
    monitor_procs = new Hashtable();
  }

  /**
   * @see IdentifierChecker.outAMonitorHeading
   */
  public void outAProcessHeading(AProcessHeading node) {
    TIdentifier ident = node.getIdentifier();
    String key = ident.getText().toUpperCase();

    checkProcess(ident);
    program = false;
    if (!local_table.isEmpty()) {
      local_table.clear();
    }
  }

  /**
   * sets inner to false if it is true or
   * not_a_program to false
   */
  public void outAProcedureDeclaration(AProcedureDeclaration node) {
    if (previous_entity == PROGRAM) {
      program = true;
    }
    else {
      monitor = true;
    }
  }

  /**
   * sets inner to false if it is true or
   * not_a_program to false
   */
  public void outAFunctionDeclaration(AFunctionDeclaration node) {
    program = true;
  }

  /**
   * sets not_a_program to false
   * and removes the current table from the list
   */
  public void outAProcessDeclaration(AProcessDeclaration node) {
    program = true;
  }

  /**
   * checks if the identifiers in the export list exist and that
   * they are not repeated in the list
   */
  public void outAMonitorDeclaration(AMonitorDeclaration node) {
    program = true;
    monitor = false;
    ((Monitor) global_table.get(monitor_name.toUpperCase())).
        setTable(monitor_procs);
  }

  /**
   * checks if the identifier exists
   */
  public void outAIdentifierIndex(AIdentifierIndex node) {
    checkId(node.getIdentifier());
  }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -