zoukankan      html  css  js  c++  java
  • 3.JavaCC 语法描述文件的格式解析

      JavaCC的语法描述文件格式如下所示:

    options {
        JavaCC的选项
    }
    
    PARSER_BEGIN(解析器类名)
    package 包名;
    import 库名;
    
    public class 解析器类名 {
        任意的Java代码
    }
    PARSER_END(解析器类名)
    
    扫描器的描述
    
    解析器的描述
    

      JavaCC和java一样将解析器的内容 定义在单个类中 ,因此会在PARSER_BEGIN和PARSER_END之间描述这个类的相关内容。

    下面拿一段实际代码来做示例,并对代码进行逐段拆分解析。

    1. 示例代码

    options {
        STATIC = false;
    }
    
    PARSER_BEGIN(Adder)
    package com.susu.testJavaCC;
    import java.io.*;
    public class Adder {
        public static void main(String[] args) {
            for (String arg : args) {
                try {
                    System.out.println(evaluate(arg));
    //                return(evaluate(arg));
                } catch (ParseException ex) {
                    System.err.println(ex.getMessage());
                }
            }
        }
    
        public static long evaluate(String src) throws ParseException {
            Reader reader = new StringReader(src);
            return new Adder(reader).expr();
        }
    }
    PARSER_END(Adder)
    
    SKIP: { <[" ", "	", "
    ", "
    "]> }
    TOKEN: {
        <INTEGER: (["0"-"9"])+>
    }
    
    long expr():
    {
        Token x, y;
    }
    {
        x=<INTEGER> "+" y=<INTEGER> <EOF>
        {
            return Long.parseLong(x.image) + Long.parseLong(y.image);
        }
    }
    

    2. 代码结构解析

    1. options块中将STATIC选项设置为false, 将该选项设置为true的话JavaCC生成的所有成员及方法都将被定义为static,若将STATIC设置为true则所生成的解析器无法在多线程环境下使用,因此该选项总是被设置为false。(STATIC的默认值为true)
    2. 从PARSER_BEING(Adder)到PARSER_END(Adder)是解析器类的定义。解析器类中需要定义的成员和方法也写在这里。为了实现即使只有Adder类也能够运行,这里定义了main函数。
    3. 之后的SKIP和TOKEN部分定义了扫描器。SKIP表示要跳过空格、制表符(tab)和换行符。TOKEN表示扫描整数字符并生成token。
    4. long expr...开始到最后的部分定义了狭义的解析器。这部分解析token序列并执行某些操作。

    3. main函数代码解析

      main函数将所有命令行参数的字符串作为计算对象的算式,依次用evaluate方法进行计算。
      evaluate方法中生成了Adder类的对象实例 。并让Adder对象来计算(解析)参数字符串src。
      要运行JavaCC生成的解析器类,需要下面2个步骤:

    1. 生成解析器类的对象实例
    2. 用生成的对象调用和需要解析的语句同名的方法

    第1点: JavaCC4.0和JavaCC5.0生成的解析器中默认定义有如下四种类型的构造函数。

    • Parser(InputStream s):第1种的构造函数是通过传入InputStream对象来构造解析的。这个构造函数无法设定输入字符串的编码,因此无法处理中文字符等。
    • Parser (InputStream s, String encoding):第2种的构造函数除了InputStream对象外,还可以设置输入字符串的编码来生成解析器。但如果要解析中文字符串或注释的话,就必须使用第2种/3种构造函数。
    • Parser(Reader r):第3种的构造函数用于解析Reader对象所读入的内容。
    • Parser (x x x x TokenManager tm):第4种是将扫描器作为参数传入。

      解析器生成后,用这个实例调用和需要解析的语法同名的方法。这里调用Adder对象的expr方法,接回开始解析,解析正常结束后会返回语义值。

  • 相关阅读:
    hdu 5446 Unknown Treasure lucas和CRT
    Hdu 5444 Elven Postman dfs
    hdu 5443 The Water Problem 线段树
    hdu 5442 Favorite Donut 后缀数组
    hdu 5441 Travel 离线带权并查集
    hdu 5438 Ponds 拓扑排序
    hdu 5437 Alisha’s Party 优先队列
    HDU 5433 Xiao Ming climbing dp
    hdu 5432 Pyramid Split 二分
    Codeforces Round #319 (Div. 1) B. Invariance of Tree 构造
  • 原文地址:https://www.cnblogs.com/suhaha/p/11697970.html
Copyright © 2011-2022 走看看