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

📄 preprocessor.java

📁 外国人写的c#语法解析器
💻 JAVA
📖 第 1 页 / 共 3 页
字号:

  /**
   * Reads the next input line and advances the internal line counter. If we are currently in multi
   * line comment mode then skip comment lines until we find a comment end.
   * 
   * @return The read line.
   * @throws IOException
   */
  protected String readLine() throws IOException
  {
    String line = null;
    
    do
    {
      line = input.readLine();
      if (traceProcessing)
        System.out.println("   : " + line);
      if (line == null)
      {
        // If the input string empty then there is no more input available in this file.
        // Return to previous input state in this case.
        reportIncludeFile("<<< " + inputState.getFilename());
        inputState.popState();
        break;
      }
      if (skip != SKIP_NONE)
        break;
      
      // First check if we are still waiting for a multi line comment to end.
      if (inMultilineComment)
      {
        int commentEndIndex = line.indexOf("*/");
        // If the comment does not end on this line then start over with the next one.
        if (commentEndIndex == -1)
          continue;
        
        // The multi line comment ends here. Remove the remaining comment part and continue processing.
        inMultilineComment = false;
        line = line.substring(commentEndIndex + 2, line.length());
        break;
      }
    }
    while (inMultilineComment);
    
    if (line == null)
      return null;
    else
      if (skip != SKIP_NONE)
        return line.trim();
      else
        return removeComments(line);
  }

  //------------------------------------------------------------------------------------------------

  /**
   * Reads and processes all input until a non-preprocessor line is found. This line is appended
   * to the current content of the currentLine string buffer that is used to feed the lexer.
   * 
   * @throws IOException Thrown when something goes wrong with reading file data.
   */
  protected void readNextLine() throws IOException
  {
    currentLine.delete(0, currentPosition);
    currentPosition = 0;
    String result = processUnconditionalInput();
    if (result != null)
      currentLine.append(result);
    currentLine.append('\n');
  }

  //------------------------------------------------------------------------------------------------

  /**
   * Adds the given search path for include files to the internal list.
   * Note that this preprocessor does nothing know about predefined pathes as used in MSVC (e.g.
   * as in <tchar.h>). So you must explicitely give these pathes too.
   * 
   * @param name The new search path to add.
   */
  public void addIncludePath(String name)
  {
    includePaths.add(name); 
  }

  //------------------------------------------------------------------------------------------------

  /**
   * Adds the given macro to the internal macro table.
   * Note: The definition must not contain the <b>#define</b> part.
   * 
   * @param macro The macro definition string.
   */
  public void addMacro(String macro)
  {
    macroTable.defineMacro(macro);
  }
  
  //------------------------------------------------------------------------------------------------
  
  public void addPreprocessorEventListener(IParseEventListener listener)
  {
    listeners.add(listener);
  }

  //------------------------------------------------------------------------------------------------

  /* (non-Javadoc)
   * @see java.io.Reader#close()
   */
  public void close() throws IOException
  {
    // Nothing to do here.
  }

  //------------------------------------------------------------------------------------------------

  /**
   * Returns the internal table of collected macro definitions.
   * 
   * @return Returns the macro table.
   */
  public MacroTable getMacroTable()
  {
    return macroTable;
  }

  //------------------------------------------------------------------------------------------------

  public boolean hadErrors()
  {
    return hadErrors;
  }
  
  //------------------------------------------------------------------------------------------------

  public boolean hadWarnings()
  {
    return hadWarnings;
  }

  //------------------------------------------------------------------------------------------------

  /* (non-Javadoc)
   * @see net.softgems.resourceparser.main.IParseEventListener#handleEvent(int, java.lang.String)
   */
  public void handleEvent(int event, String message)
  {
    // This method is called here only during an expression evaluation and is used to forward
    // the incoming events to the owner of this preprocessor.
    doEvent(event, message, false);
  }
  
  //------------------------------------------------------------------------------------------------
  
  /**
   * Sets a new input state up so following read attempts by the lexer are directed to the new
   * preprocessor.
   * 
   * @param filename The file to include.
   * @return <b>true</b> if a new preprocessor was set up, otherwise <b>false</b>.
   * @throws IOException
   * @throws FileNotFoundException
   */
  public boolean includeFile(String filename) throws IOException, FileNotFoundException
  {
    boolean result = false;
    
    // The map processedIncludes contains files, which were marked with the "#pragma once" directive
    // and hence should automatically not be included more than once.
    if (!processedIncludes.containsKey(filename))
    {
      // To make relative includes from the included file possible switch to the resulting
      // directory of this include file. Restore the value after return.
      File canonicalFile = null;
  
      // Try to locate the include file without include path first (relative to application root)
      File file = new File(filename);

      // Convert eventual further subfolders in the file to one canonical file,
      // so we have resolved links and no special folders like "." or ".." etc. anymore.
      canonicalFile = file.getCanonicalFile();
      if (!file.isAbsolute())
      {
        // If the file is relative then first try to access it as if it is using the current
        // user dir as base folder.
        if (!canonicalFile.canRead())
        {
          // We have a relative file, which is not accessible from the current user directory.
          // Try each include path until we have access.
          for (Iterator iterator = includePaths.iterator(); iterator.hasNext();)
          {
            String path = (String) iterator.next();
            if (!path.endsWith(File.separator))
              path += File.separator;
            
            File testFile = new File(path + filename);
            if (testFile.exists())
            {
              canonicalFile = testFile.getCanonicalFile();
              break;
            }
          }
        }
      }
      
      if (canonicalFile.canRead())
      {
        reportIncludeFile(">>> " + filename);
        
        // If we can read the file then set up a new preprocessor instance. The sub preprocessor 
        // uses the same input state, include pathes and defined symbols as this one.
        InputConverter input = new InputConverter(inputState, new FileInputStream(canonicalFile), 
          DEFAULT_CHARSET);
        Preprocessor preprocessor = new Preprocessor(input, this, inputState, traceProcessing);
        inputState.pushState(preprocessor, canonicalFile.getName(), canonicalFile.getParent());
        preprocessor.addPreprocessorEventListener(
          new IParseEventListener() 
          {
            public void handleEvent(int event, String message)
            {
              doEvent(event, message, false);
            };
          }
        );
        preprocessor.init();
        result = true;
      }
      else
        reportWarning("Cannot access include file \"" + filename + "\"");
    }
    return result;
  }

  //------------------------------------------------------------------------------------------------

  public void init()
  {
    // Microsoft's resource compiler handles *.c and *.h files in a special way. Everything except 
    // preprocessor lines is automatically skipped in such files.
    // See also: "Using #include Directive with Windows Resource Compiler", KB Q80945.
    String filename = inputState.getFilename();
    skipNonPPLines = filename.toLowerCase().endsWith(".c") || filename.toLowerCase().endsWith(".h");
  }
  
  //------------------------------------------------------------------------------------------------

  /** 
   * This method is executed by the preprocessor internally when it detected an illegal
   *  state that cannot be recovered from.
   */
  public void panic(String s)
  {
    doEvent(IParseEventListener.PANIC, "RC lexer panic: " + s, true);
  }
  
  //------------------------------------------------------------------------------------------------

  /* (non-Javadoc)
   * @see java.io.Reader#read()
   */
  public int read() throws IOException
  {
    if (currentLine.length() < (currentPosition + 1))
      readNextLine();
    
    if (currentLine.length() == 0)
      return -1;
    else
      return currentLine.charAt(currentPosition++);
  }

  //------------------------------------------------------------------------------------------------

  /* (non-Javadoc)
   * @see java.io.Reader#read(char[], int, int)
   */
  public int read(char[] cbuf, int off, int len) throws IOException
  {
    if (currentLine.length() < (currentPosition + len))
      readNextLine();
    
    if (currentLine.length() == 0)
      return -1;
    else
    {
      int actualLength = Math.min(currentLine.length() - currentPosition, len);
      currentLine.getChars(currentPosition, actualLength, cbuf, off);
      currentPosition += actualLength;
      
      return actualLength;
    }
  }

  //------------------------------------------------------------------------------------------------

  /**
   * Removes the given listener from the internal list. If the listerner is not in this list
   * then the method does nothing.
   * 
   * @param listener The listener to be removed.
   */
  public void removePreprocessorEventListener(IParseEventListener listener)
  {
    listeners.remove(listener);
  }
  
  //------------------------------------------------------------------------------------------------

  /**
   * Removes the symbol with the given name from the internal symbol table. If the symbol does not
   * exist then nothing happens.
   * 
   * @param name The name of the symbol to be removed.
   */
  public void removeSymbol(String name)
  {
    macroTable.undefineMacro(name);
  }
  
  //------------------------------------------------------------------------------------------------
  
  /**
   * Reports an error to the calling application.
   * 
   * @param s Error message to report.
   */
  public void reportError(String s)
  {
    doEvent(IParseEventListener.ERROR, s, inputState.getFullFilename() != null);
  }

  //------------------------------------------------------------------------------------------------

  /**
   * Reports the names of all files, which are included during the preprocessing step.
   * 
   * @param filen The name of the file that is about to be processed.
   */
  public void reportIncludeFile(String file)
  {
    doEvent(IParseEventListener.INCLUDE_FILE, file, inputState.getFullFilename() != null);
  }

  //------------------------------------------------------------------------------------------------

  /**
   * Reports general information to the calling application.
   * 
   * @param s Information message to report.
   */
  public void reportInfo(String s)
  {
    doEvent(IParseEventListener.INFORMATION, s, inputState.getFullFilename() != null);
  }

  //------------------------------------------------------------------------------------------------
  
  /**
   * Reports a warning to the calling application.
   * 
   * @param s Warning message to report.
   */
  public void reportWarning(String s)
  {
    doEvent(IParseEventListener.WARNING, s, inputState.getFullFilename() != null);
  }

  //------------------------------------------------------------------------------------------------

}

⌨️ 快捷键说明

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