Exemplo n.º 1
0
/**
 *
 *
 * <h1>TypeDefinitionsParser</h1>
 *
 * <p>Parse Pascal type definitions.
 *
 * <p>Copyright (c) 2009 by Ronald Mak
 *
 * <p>For instructional purposes only. No warranties.
 */
public class TypeDefinitionsParser extends DeclarationsParser {
  /**
   * Constructor.
   *
   * @param parent the parent parser.
   */
  public TypeDefinitionsParser(PascalParserTD parent) {
    super(parent);
  }

  // Synchronization set for a type identifier.
  private static final EnumSet<PascalTokenType> IDENTIFIER_SET =
      DeclarationsParser.VAR_START_SET.clone();

  static {
    IDENTIFIER_SET.add(IDENTIFIER);
  }

  // Synchronization set for the = token.
  private static final EnumSet<PascalTokenType> EQUALS_SET =
      ConstantDefinitionsParser.CONSTANT_START_SET.clone();

  static {
    EQUALS_SET.add(EQUALS);
    EQUALS_SET.add(SEMICOLON);
  }

  // Synchronization set for what follows a definition or declaration.
  private static final EnumSet<PascalTokenType> FOLLOW_SET = EnumSet.of(SEMICOLON);

  // Synchronization set for the start of the next definition or declaration.
  private static final EnumSet<PascalTokenType> NEXT_START_SET =
      DeclarationsParser.VAR_START_SET.clone();

  static {
    NEXT_START_SET.add(SEMICOLON);
    NEXT_START_SET.add(IDENTIFIER);
  }

  /**
   * Parse type definitions.
   *
   * @param token the initial token.
   * @throws Exception if an error occurred.
   */
  public void parse(Token token) throws Exception {
    token = synchronize(IDENTIFIER_SET);

    // Loop to parse a sequence of type definitions
    // separated by semicolons.
    while (token.getType() == IDENTIFIER) {
      String name = token.getText().toLowerCase();
      SymTabEntry typeId = symTabStack.lookupLocal(name);

      // Enter the new identifier into the symbol table
      // but don't set how it's defined yet.
      if (typeId == null) {
        typeId = symTabStack.enterLocal(name);
        typeId.appendLineNumber(token.getLineNumber());
      } else {
        errorHandler.flag(token, IDENTIFIER_REDEFINED, this);
        typeId = null;
      }

      token = nextToken(); // consume the identifier token

      // Synchronize on the = token.
      token = synchronize(EQUALS_SET);
      if (token.getType() == EQUALS) {
        token = nextToken(); // consume the =
      } else {
        errorHandler.flag(token, MISSING_EQUALS, this);
      }

      // Parse the type specification.
      TypeSpecificationParser typeSpecificationParser = new TypeSpecificationParser(this);
      TypeSpec type = typeSpecificationParser.parse(token);

      // Set identifier to be a type and set its type specificationt.
      if (typeId != null) {
        typeId.setDefinition(TYPE);
      }

      // Cross-link the type identifier and the type specification.
      if (type != null && typeId != null) {
        if (type.getIdentifier() == null) {
          type.setIdentifier(typeId);
        }
        typeId.setTypeSpec(type);
      } else {
        token = synchronize(FOLLOW_SET);
      }

      token = currentToken();
      TokenType tokenType = token.getType();

      // Look for one or more semicolons after a definition.
      if (tokenType == SEMICOLON) {
        while (token.getType() == SEMICOLON) {
          token = nextToken(); // consume the ;
        }
      }

      // If at the start of the next definition or declaration,
      // then missing a semicolon.
      else if (NEXT_START_SET.contains(tokenType)) {
        errorHandler.flag(token, MISSING_SEMICOLON, this);
      }

      token = synchronize(IDENTIFIER_SET);
    }
  }
}
Exemplo n.º 2
0
/**
 *
 *
 * <h1>VariableDeclarationsParser</h1>
 *
 * <p>解析变量申明
 *
 * <p>Copyright (c) 2009 by Ronald Mak
 *
 * <p>For instructional purposes only. No warranties.
 */
public class VariableDeclarationsParser extends DeclarationsParser {
  // 标识符怎么定义的?同是变量申明,上下文不一样,定义不一样
  private Definition definition;

  public VariableDeclarationsParser(PascalParserTD parent) {
    super(parent);
  }

  /**
   * 设置此申明的定义
   *
   * @param definition the definition to set.
   */
  protected void setDefinition(Definition definition) {
    this.definition = definition;
  }

  // 变量申明的同步集
  static final EnumSet<PascalTokenType> IDENTIFIER_SET = DeclarationsParser.VAR_START_SET.clone();

  static {
    IDENTIFIER_SET.add(IDENTIFIER);
    IDENTIFIER_SET.add(END);
    IDENTIFIER_SET.add(SEMICOLON);
  }

  // 下一个定义或申明的同步集
  static final EnumSet<PascalTokenType> NEXT_START_SET =
      DeclarationsParser.ROUTINE_START_SET.clone();

  static {
    NEXT_START_SET.add(IDENTIFIER);
    NEXT_START_SET.add(SEMICOLON);
  }

  public void parse(Token token) throws Exception {
    token = synchronize(IDENTIFIER_SET);

    // 遍历由分号分割的一系列变量申明
    while (token.getType() == IDENTIFIER) {

      // 解析每一个子表标识申明,比如 a,b,c : int
      parseIdentifierSublist(token);

      token = currentToken();
      TokenType tokenType = token.getType();

      // 一个定义由分号结束
      if (tokenType == SEMICOLON) {
        while (token.getType() == SEMICOLON) {
          token = nextToken(); // consume the ;
        }
      } else if (NEXT_START_SET.contains(tokenType)) {
        // 没有分号便开始下一个了。
        errorHandler.flag(token, MISSING_SEMICOLON, this);
      }

      token = synchronize(IDENTIFIER_SET);
    }
  }

  // 子表标识同步集,这里a,b,c: int 中的a,b,c算作子表
  static final EnumSet<PascalTokenType> IDENTIFIER_START_SET = EnumSet.of(IDENTIFIER, COMMA);

  // 标识符后的同步集
  private static final EnumSet<PascalTokenType> IDENTIFIER_FOLLOW_SET =
      EnumSet.of(COLON, SEMICOLON);

  static {
    IDENTIFIER_FOLLOW_SET.addAll(DeclarationsParser.VAR_START_SET);
  }

  // 逗号的同步集
  private static final EnumSet<PascalTokenType> COMMA_SET =
      EnumSet.of(COMMA, COLON, IDENTIFIER, SEMICOLON);

  /**
   * 解析标识符子表及类型说明
   *
   * @param token the current token.
   * @return 一个申明中的子表标识符列表
   * @throws Exception
   */
  protected ArrayList<SymTabEntry> parseIdentifierSublist(Token token) throws Exception {
    ArrayList<SymTabEntry> sublist = new ArrayList<SymTabEntry>();

    do {
      token = synchronize(IDENTIFIER_START_SET);
      SymTabEntry id = parseIdentifier(token);

      if (id != null) {
        sublist.add(id);
      }

      token = synchronize(COMMA_SET);
      TokenType tokenType = token.getType();

      // 找逗号
      if (tokenType == COMMA) {
        token = nextToken(); // 有逗号吞掉以便下一个

        if (IDENTIFIER_FOLLOW_SET.contains(token.getType())) {
          errorHandler.flag(token, MISSING_IDENTIFIER, this);
        }
      } else if (IDENTIFIER_START_SET.contains(tokenType)) {
        errorHandler.flag(token, MISSING_COMMA, this);
      }
    } while (!IDENTIFIER_FOLLOW_SET.contains(token.getType()));

    // 冒号后面的类型
    TypeSpec type = parseTypeSpec(token);

    // 将子表中的每个变量的类型设置上,比如a,b,c:int,先解析了a,b,c,然后解析了int类型
    // 那么这儿就会给a,b,c设置上int类型
    for (SymTabEntry variableId : sublist) {
      variableId.setTypeSpec(type);
    }

    return sublist;
  }

  /**
   * 解析标识符
   *
   * @param token
   * @return 对应符号表项
   * @throws Exception
   */
  private SymTabEntry parseIdentifier(Token token) throws Exception {
    SymTabEntry id = null;

    if (token.getType() == IDENTIFIER) {
      String name = token.getText().toLowerCase();
      id = symTabStack.lookupLocal(name);

      // 申明必须得没有,否则重定义了
      if (id == null) {
        id = symTabStack.enterLocal(name);
        id.setDefinition(definition);
        id.appendLineNumber(token.getLineNumber());
      } else {
        errorHandler.flag(token, IDENTIFIER_REDEFINED, this);
      }

      token = nextToken();
    } else {
      errorHandler.flag(token, MISSING_IDENTIFIER, this);
    }

    return id;
  }

  // 类型冒号处的同步集
  private static final EnumSet<PascalTokenType> COLON_SET = EnumSet.of(COLON, SEMICOLON);

  /**
   * 解析变量申明里的类型
   *
   * @param token 当前token
   * @return 类型说明
   * @throws Exception
   */
  protected TypeSpec parseTypeSpec(Token token) throws Exception {
    // 同步在:处
    token = synchronize(COLON_SET);
    if (token.getType() == COLON) {
      token = nextToken(); // 吞掉 :
    } else {
      errorHandler.flag(token, MISSING_COLON, this);
    }

    // 解析类型说明
    TypeSpecificationParser typeSpecificationParser = new TypeSpecificationParser(this);
    TypeSpec type = typeSpecificationParser.parse(token);

    return type;
  }
}