java - 使用 Java 的 HTML 词法分析器

标签 java html lexical-analysis

我是一名学生程序员,我正在尝试为我的计算机科学类(class)之一构建 HTML 代码的词法分析器,其中输出应该是 HTML 代码的各个标记和词位。但是当我编译并运行分析器时,输出似乎有问题。

给出以下 HTML 代码:

    <table>
    <tr><td>temp</td><td>temp2</td></tr>
    </table>

输出应该是:

    TOKEN       LEXEME
    ------------------
    TAGIDENT    <table
    GTHAN       >
    TAGIDENT    <tr
    GTHAN       >
    TAGIDENT    <td
    GTHAN       >
    IDENT       temp
    ENDTAGHEAD  </
    IDENT       td
    GTHAN       >
    TAGIDENT    <td
    GTHAN       >
    IDENT       temp2
    ENDTAGHEAD  </
    IDENT       td
    GTHAN       >
    ENDTAGHEAD  </
    IDENT       tr
    GTHAN       >

目前,这是我的代码:

import java.io.*;
import java.util.*;

public class LexAnalyzer {
public static void main(String[] args) {
    try { 
        String input = "" , s = "";
        Token t;
        BufferedReader in = new BufferedReader(new FileReader(new        File("Sample.html")));
        while((s = in.readLine()) != null) {
            input += s;
        }
        System.out.println(input);
        System.out.println("TOKEN       LEXEME");
        System.out.println("------------------");
        ArrayList<Token> a = getToken(input);
        for(int i = 0; i < a.size(); i++) {
            System.out.println(a.get(i).getId() + "    " + a.get(i).getLexeme());
        }
    }

    catch(Exception e) {
        e.printStackTrace();
    }
}

public static ArrayList<Token> getToken(String input) {
    String lexeme = ""; //lexeme = TOKEN = ie. TAGIDENT
    Token t = null;
    ArrayList<Token> a = new ArrayList<Token>();
    for(int i = 0; i < input.length(); i++) {
        if(input.charAt(i) == '<') {
            lexeme += input.charAt(i); 
            i++;
            //case 1: if followed by ! < = COMMENT
            if(input.charAt(i) == '!') {
                lexeme += input.charAt(i);
                i++;
                while(input.charAt(i) != '>') {
                    lexeme += input.charAt(i);
                    i++;
                }
                input = input.substring(lexeme.length(), input.length());
            }

            //case 2: if followed by letter < = TAGIDENT
            else if(isALetter(input.charAt(i))) {
                lexeme += input.charAt(i);
                i++;
                while(input.charAt(i) != '>' && input.charAt(i) != ' ') {
                    lexeme += input.charAt(i);
                    i++;
                }
                t = new Token("TAGIDENT", lexeme);
                input = input.substring(lexeme.length(), input.length());
                a.add(t);
            }

            //case 3: if followed by number or space < = LTHAN
            else if((isANumber(input.charAt(i)))) {
                lexeme += input.charAt(i);
                i++;
                while(input.charAt(i) != '<' || input.charAt(i) == ' ') { 
                    lexeme += input.charAt(i);
                    i++;
                }
                t = new Token("LTHAN", lexeme);
                input = input.substring(lexeme.length(), input.length());
                a.add(t);
            }

            //case 4: if followed by / < = ENDTAGHEAD
            else if(input.charAt(i) == '/') {
                lexeme += input.charAt(i);
                i++;
                //case 5: after ENDTAGHEAD -> IDENT
                if(isALetter(input.charAt(i))) {
                    lexeme += input.charAt(i);
                    i++;
                    while(input.charAt(i) != '>') {
                        lexeme += input.charAt(i);
                        i++;
                    }
                    t = new Token("IDENT", lexeme);
                    input = input.substring(lexeme.length(), input.length());
                    a.add(t);
                }
                t = new Token("ENDTAGHEAD", lexeme);
                input = input.substring(lexeme.length(), input.length());
                a.add(t);
            }
        }

        else if(input.charAt(i) == '>') {
            lexeme += input.charAt(i);
            i++;
            t = new Token("GTHAN", lexeme);
            input = input.substring(lexeme.length(), input.length());
        }
    }
    return a;
}

public static boolean isALetter(char inputChar) {
    Boolean itIsALetter = false;
    if("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM".indexOf(inputChar) != -1) {
        itIsALetter = true;
    }
    return itIsALetter;
}

public static boolean isANumber(char inputChar) {
    Boolean itIsANumber = false;
    if("1234567890".indexOf(inputChar) != -1) {
        itIsANumber = true;
    }
    return itIsANumber;
}

}

token 类别:

public class Token {
    String id, lexeme;

    public Token(String id, String lexeme) {
        this.id = id;
        this.lexeme = lexeme;
    }

    public String getId() {
        return id;
    }

    public String getLexeme() {
        return lexeme;
    }
}

我的代码的输出:

    TOKEN       LEXEME
    ------------------
    TAGIDENT    <table
    IDENT       <table>></td
    ENDTAGHEAD  <table>></td

关于如何修复我的代码有什么建议吗?非常感谢!

最佳答案

每当您读取 token 时:

while(input.charAt(i) != '>' && input.charAt(i) != ' ') {
    lexeme += input.charAt(i);
    i++;
}

您应该在 while 循环之后再添加一行:

lexeme += input.charAt(i);

为了读取最后一个结束字符>。一旦您修复了代码中的所有这些位置(或者更好的是,重构您的代码并将其提取到外部帮助器方法) - 您将获得完整的 token 。

关于java - 使用 Java 的 HTML 词法分析器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21507331/

相关文章:

javascript - 如何在图像 CSS 上放置一个思想泡泡

ruby - Ruby 如何知道 '/' 何时是除号,以及何时开始正则表达式?

yacc - yytext [0]是什么意思?

java - WSDL 发布后发生更改

java - 将毫秒持续时间转换为 Java 中持续时间的 ISO 8601 精确字符串格式

javascript - 打造像素艺术创作者

c++ - 提高编译器中 std::string 的效率

java - 执行jar时相对路径不起作用

java - 泛型对象创建在 Eclipse 中显示错误,但在 Maven 中编译

javascript - jQuery 将子级添加到父级