public QWordBuilder loadRules(Reader r) {
        BufferedReader br = Streams.buffr(r);

        // 按行读取
        try {
            String line;
            int lineNumber = 0;
            while (null != (line = br.readLine())) {
                lineNumber++;
                line = Strings.trim(line);
                // 忽略空行和注释行
                if (Strings.isEmpty(line) || line.startsWith("#"))
                    continue;

                // 如果行以 $ 开头表示一个约束描述
                if (line.startsWith("$")) {
                    QWordRule qr = new QWordRule();
                    // 寻找到第一个 :
                    int pos = line.indexOf(':');
                    // 神码？竟敢木油冒号？！ 抛错对付你 >:D
                    if (pos == -1)
                        throw Lang.makeThrow("invalid rule line %d : %s", lineNumber, line);
                    // 获取名称
                    qr.key = Strings.trim(line.substring(1, pos));
                    String regex;

                    // 看看是否是简要模式
                    if (line.charAt(pos + 1) == ':') {
                        regex = "^(" + Strings.trim(line.substring(pos + 2)) + ")(.*)$";
                    }
                    // 普通模式
                    else {
                        regex = Strings.trim(line.substring(pos + 1));
                    }
                    // 得到正则表达式
                    qr.regex = Pattern.compile(regex);

                    // 再读一行作为详细描述
                    line = Strings.trim(br.readLine());
                    lineNumber++;

                    // 分隔
                    pos = line.lastIndexOf('=');

                    // 神码？竟敢木油等号？！ 抛错对付你 >:D
                    if (pos == -1)
                        throw Lang.makeThrow("invalid rule line %d : %s", lineNumber, line);

                    qr.type = QCndType.valueOf(Strings.trim(line.substring(pos + 1)));
                    qr.seg = Segments.create(Strings.trim(line.substring(0, pos)));

                    rules.add(qr);

                }
                // 其他的忽略

            }
        }
        catch (IOException e) {
            throw Lang.wrapThrow(e);
        }

        return this;
    }