Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java StreamTokenizer会破坏整数和松散周期_Java_Tokenize - Fatal编程技术网

Java StreamTokenizer会破坏整数和松散周期

Java StreamTokenizer会破坏整数和松散周期,java,tokenize,Java,Tokenize,我已经使用并修改了下面的代码,它在使用Java的StreamTokenizer标记Java代码方面做得非常好。其数字处理存在问题,但: 它将所有整数转换为双精度整数。我可以通过测试num%1==0来克服这个问题,但这感觉像是一个黑客 更为关键的是,一个。下面的空白被视为一个数字。“Class.method()”是合法的Java语法,但生成的标记是[Word“Class”]、[Whitespace”“]、[Number 0.0]、[Word“method”]、[Symbol”(“])和[Symbo

我已经使用并修改了下面的代码,它在使用Java的StreamTokenizer标记Java代码方面做得非常好。其数字处理存在问题,但:

  • 它将所有整数转换为双精度整数。我可以通过测试num%1==0来克服这个问题,但这感觉像是一个黑客
  • 更为关键的是,一个。下面的空白被视为一个数字。“Class.method()”是合法的Java语法,但生成的标记是[Word“Class”]、[Whitespace”“]、[Number 0.0]、[Word“method”]、[Symbol”(“])和[Symbol”)]
  • 我很乐意完全关闭StreamTokenizer的数字解析,并自己从单词标记解析数字,但是注释st.parseNumbers()似乎没有效果

    public class JavaTokenizer {
    
    private String code;
    
    private List<Token> tokens;
    
    public JavaTokenizer(String c) {
        code = c;
        tokens = new ArrayList<>();
    }
    
    public void tokenize() {
        try {
            // Create the tokenizer
            StringReader sr = new StringReader(code);
            StreamTokenizer st = new StreamTokenizer(sr);
    
            // Java-style tokenizing rules
            st.parseNumbers();
            st.wordChars('_', '_');
            st.eolIsSignificant(false);
    
            // Don't want whitespace tokens
            //st.ordinaryChars(0, ' ');
    
            // Strip out comments
            st.slashSlashComments(true);
            st.slashStarComments(true);
    
            // Parse the file
            int token;
            do {
                token = st.nextToken();
                switch (token) {
                case StreamTokenizer.TT_NUMBER:
                    // A number was found; the value is in nval
                    double num = st.nval;
                    if(num % 1 == 0)
                      tokens.add(new IntegerToken((int)num);
                    else
                      tokens.add(new FPNumberToken(num));
                    break;
                case StreamTokenizer.TT_WORD:
                    // A word was found; the value is in sval
                    String word = st.sval;
                    tokens.add(new WordToken(word));
                    break;
                case '"':
                    // A double-quoted string was found; sval contains the contents
                    String dquoteVal = st.sval;
                    tokens.add(new DoubleQuotedStringToken(dquoteVal));
                    break;
                case '\'':
                    // A single-quoted string was found; sval contains the contents
                    String squoteVal = st.sval;
                    tokens.add(new SingleQuotedStringToken(squoteVal));
                    break;
                case StreamTokenizer.TT_EOL:
                    // End of line character found
                    tokens.add(new EOLToken());
                    break;
                case StreamTokenizer.TT_EOF:
                    // End of file has been reached
                    tokens. add(new EOFToken());
                    break;
                default:
                    // A regular character was found; the value is the token itself
                    char ch = (char) st.ttype;
                    if(Character.isWhitespace(ch))
                        tokens.add(new WhitespaceToken(ch));
                    else
                        tokens.add(new SymbolToken(ch));
                    break;
                }
            } while (token != StreamTokenizer.TT_EOF);
            sr.close();
        } catch (IOException e) {
        }
    }
    
    public List<Token> getTokens() {
        return tokens;
    }
    
    }
    
    公共类JavaTokenizer{
    私有字符串码;
    私有列表令牌;
    公共JavaTokenizer(字符串c){
    代码=c;
    令牌=新的ArrayList();
    }
    公共void标记化(){
    试一试{
    //创建标记器
    StringReader sr=新的StringReader(代码);
    StreamTokenizer st=新的StreamTokenizer(sr);
    //Java风格的标记化规则
    圣帕西数字();
    圣沃德查斯酒店;
    st.Eologisicant(假);
    //不要空白标记
    //圣普通夏尔(0,);
    //删除评论
    st.slashSlashComments(正确);
    st.Slashstar评论(正确);
    //解析文件
    int标记;
    做{
    token=st.nextToken();
    交换机(令牌){
    案例StreamTokenizer.TT_编号:
    //找到一个数字;该值为nval
    双数值=标准nval;
    如果(数值%1==0)
    add(新的IntegerToken((int)num);
    其他的
    添加(新的FPNumberToken(num));
    打破
    case StreamTokenizer.TT_字:
    //找到一个单词;该值为sval
    字符串字=st.sval;
    添加(新单词token(word));
    打破
    案例'':
    //找到双引号字符串;sval包含内容
    字符串dquoteVal=st.sval;
    添加(新的DoubleQuotedStringToken(dquoteVal));
    打破
    案例'\'':
    //找到一个带引号的字符串;sval包含内容
    字符串squoteVal=st.sval;
    添加(新的SingleQuotedStringToken(squoteVal));
    打破
    案例StreamTokenizer.TT_下线:
    //找到行尾字符
    添加(新的EOLToken());
    打破
    case StreamTokenizer.TT_EOF:
    //已到达文件末尾
    添加(新的EOFToken());
    打破
    违约:
    //找到了一个常规字符;该值是标记本身
    char ch=(char)st.ttype;
    if(字符.isWhitespace(ch))
    添加(新的WhitespaceToken(ch));
    其他的
    添加(新的SymbolToken(ch));
    打破
    }
    }while(token!=StreamTokenizer.TT_EOF);
    高级关闭();
    }捕获(IOE异常){
    }
    }
    公共列表getTokens(){
    归还代币;
    }
    }
    
    有机会时,我会调查parboiled。与此同时,我为让它正常工作而实施的令人厌恶的解决方案是:

    private static final String DANGLING_PERIOD_TOKEN = "___DANGLING_PERIOD_TOKEN___";
    
    然后在tokenize()中

    此解决方案专门针对我的需要,即不关心原始空格是什么(因为它在插入的“标记”周围添加了一些空格”)

    parseNumbers()在默认情况下处于“开”状态。使用resetSyntax()关闭数字解析和所有其他预定义字符类型,然后启用所需的字符类型


    这就是说,手动数字解析可能会因为计算点和指数而变得棘手……使用扫描仪和正则表达式,实现您自己的标记器应该相对简单,完全符合您的需要。例如,您可能想看看
    标记器
    内部类:(最后约120 LOC)

    我已经使用了各种内置Java标记器类,我的收获是它们实际上功能不强。看看真正的解析器(它们有一个Java解析器,都是预先配置好的,随时可以使用,顺便说一句,不要试着自己制作。)也许你可以在“word chars”中添加
    “,参见javadocOh,我知道,但ANTLR庞大而复杂,功能远远超出我的需要,而这仅仅是一个缺陷,无法完全满足我的需要,因此,如果我能解决这个问题,将比更换整个系统少几个小时的工作system@RC,很有趣。我不确定我是否理解StreamTokenizer.wordChars()上的javadoc。似乎只使用从firstArg到secondArg的字符来标识单词,但我偷来的代码示例将两个Arg都设置为下划线,并且它仍然可以识别单词。我还尝试将其设置为.wordChars(0x23,0xFF),其中包括句号,无法识别行为上的任何差异。我不是StringTokenizer方面的专家,抱歉,如果antlr对您来说太大,也许您应该看看这一点,这会更有意义。它现在工作得好多了。我希望文档能更清楚地说明parseNumbers()没有任何效果,除非resetSyntax()他被叫来了。
    //a period following whitespace, not followed by a digit is a "dangling period"
    code = code.replaceAll("(?<=\\s)\\.(?![0-9])", " "+DANGLING_PERIOD_TOKEN+" ");
    
    case StreamTokenizer.TT_WORD:
      // A word was found; the value is in sval
      String word = st.sval;
      if(word.equals(DANGLING_PERIOD_TOKEN))
        tokens.add(new SymbolToken('.'));
      else
        tokens.add(new WordToken(word));
      break;