zoukankan      html  css  js  c++  java
  • 修改openJDK7的javac,使得java支持单引号字符串

    成功编译了openJDK后,才发现原来javac的这部分代码完全是由java语言实现的,所以可以把javac的代码单独提出来,放到eclipse里面,并且用eclipse编译和调试。这样真的超方便。。

    刚开始做了一个很简单的修改,让java支持单引号的字符串(只作为练习)。思想很简单,找到Scanner的代码,把处理单引号的代码修改为处理双引号的代码即可。

    过程如下:

    1.eclipse中新建一个工程。然后把openJDK7里面目录:openjdk7\langtools\src\share\classes \com,全部导入到eclipse中,运行。可能会遇到一个版本的问题,就是编译时的javac版本和eclipse环境中,配置 Preferences->compiler 和Preferences->buildpath两个里面的版本一致即可。可以生成javac,测试没有问题。。

    2.进入com.sun.tools.javac.Main,里面有一个main方法就是javac最外层的调用。它调用了com.sun.tools.javac.main.Main的compile方法进入编译。

    3.单步跟踪,找到真正scanner和parser的位置。前面调用几个类大致如下:com.sun.tools.javac.Main->com.sun.tools.javac.main.Main->com.sun.tools.javac.main.JavaCompiler->com.sun.tools.javac.parser.JavacParser->com.sun.tools.javac.parser.Scanner. 最后可以发现Scanner的nextToken方法,就是扫描下一个符合的方法。

    4.进入com.sun.tools.javac.parser.Scanner.nextToken(),ctrl+F搜索  '\'' 找到处理单引号的代码。如下

    01        case '\'':
    02                    scanChar();
    03                    if (ch == '\'') {
    04                        lexError("empty.char.lit");
    05                    } else {
    06                        if (ch == CR || ch == LF)
    07                            lexError(pos, "illegal.line.end.in.char.lit");
    08                        scanLitChar();
    09                        if (ch == '\'') {
    10                            scanChar();
    11                            token = CHARLITERAL;
    12                        } else {
    13                            lexError(pos, "unclosed.char.lit");
    14                        }
    15                    }
    16                    return;

    这段代码下面就有处理双引号(也就是java里面真正支持的字符串)的代码,参照此代码,把处理单引号的代码修改成以下的即可:这是我修改后的代码:

    01case '\'':
    02                    scanChar();
    03                    if (ch == '\'') {
    04                        lexError("empty.char.lit");
    05                    } else {
    06                        if (ch == CR || ch == LF)
    07                            lexError(pos, "illegal.line.end.in.char.lit");
    08                        scanLitChar();
    09                        if (ch == '\'') {
    10                            scanChar();
    11                            token = CHARLITERAL;
    12                        } else {//////////what i add///////
    13                            while (ch != '\'' && ch != CR && ch != LF && bp < buflen)
    14                                scanLitChar();
    15                            if (ch == '\'') {
    16                                token = STRINGLITERAL;
    17                                scanChar();
    18                            } else {
    19                                lexError(pos, "unclosed.str.lit");
    20                            }
    21                             
    22                            //lexError(pos, "unclosed.char.lit");
    23                        }
    24                    }
    25                    return;
    这样,如果一个单引号的字符串,它的长度为1,那么javac会把它当做字符。而如果长度大于1,就会当做字符串处理。

    测试没有问题。。

  • 相关阅读:
    Android开发之下载服务器上的一张图片到本地java代码实现HttpURLConnection
    控制台——屏蔽Ctrl+C快捷键对窗体的关闭功能
    控制台——禁用关闭按钮
    控制台——对WIN32 API的使用(user32.dll)
    控制台——对窗口句柄的操作
    控制台——防止程序重复启动
    Json——一般应用
    SQL——将两列合并成一列
    Xamarin在VS2012没有智能提示的解决办法
    C#的Xamarin开发小米盒子应用并以WCF实现微信通知
  • 原文地址:https://www.cnblogs.com/shihao/p/2756542.html
Copyright © 2011-2022 走看看