Java中的HTML Lexer

Java中的HTML Lexer,java,regex,posix,finite-automata,state-machine,Java,Regex,Posix,Finite Automata,State Machine,我正在尝试制作一个简单的Lexer,以了解它们是如何工作的。我试图找出一个好的POSIX字符串,它可以捕获任何类型的HTML标签。我做了一个几乎可以工作,但在更复杂的标签上失败了,比如meta标签等等。到目前为止,这就是我所拥有的: "<\\p{Alnum}+(\\p{Space}\\p{Alnum}+\\p{Space}*=\"*\\p{Space}*\\p{Alnum}+\"*)*\\p{Space}*>" “” 这个POSIX字符串捕获了很多标记,但是遗漏了一些,比如元标记

我正在尝试制作一个简单的Lexer,以了解它们是如何工作的。我试图找出一个好的POSIX字符串,它可以捕获任何类型的HTML标签。我做了一个几乎可以工作,但在更复杂的标签上失败了,比如meta标签等等。到目前为止,这就是我所拥有的:

"<\\p{Alnum}+(\\p{Space}\\p{Alnum}+\\p{Space}*=\"*\\p{Space}*\\p{Alnum}+\"*)*\\p{Space}*>"
“”
这个POSIX字符串捕获了很多标记,但是遗漏了一些,比如元标记和文档标记。这是一个失败的标记:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

任何帮助都将不胜感激。我知道这可能不是制作Lexer的最佳方法,但这只是为了帮助我理解Regex的工作原理。

除了引号以外的任何东西 对于属性的值,正确的扫描方式是匹配任何不是引号的内容。该部分的正则表达式如下所示:

    \"[^\"]*\"
我不知道你为什么要用“*”;引号不能重复。还有其他问题,比如允许到处都是空格,或者除了双引号之外接受单引号(
name='value'
name=”value“
)的替代品。但是还有一个更大的问题,所以我不会挑剔

过度词汇量 更重要的一点是,您在词法分析器中塞进了太多的解析。词法分析器的工作是将字符流转换为标记流。标记是文本中不可分割的小单元。我不会尝试将整个开始标记、元素名称、属性和所有内容作为单个标记进行解析

相反,您应该撬出标记的较小部分:开角括号、标识符、标识符、等号、字符串、闭角括号。让词法分析器识别这些部分,并让解析器按照顺序确定这些标记构成元素标记。

除引号外的任何内容 对于属性的值,正确的扫描方式是匹配任何非引号的内容。仅该部分的正则表达式如下所示:

    \"[^\"]*\"
我不知道你为什么有
\“*
;引号不能重复。还有其他一些问题,比如在任何地方都允许空白,或者除了双引号之外接受单引号(
name='value'
name=“value”
的替代方案)。但还有一个更大的问题,所以我不会挑剔

过度词汇量 更重要的一点是,你在词法分析器中塞进了太多的语法分析。lexer的工作是将字符流转换为令牌流。标记是文本中不可分割的小单位。我不会试图将整个开始标记、元素名、属性和所有内容作为单个标记进行解析


相反,您应该撬出标记的较小部分:开角括号、标识符、标识符、等号、字符串、闭角括号。让词法分析器识别这些片段,并将其留给解析器,以确定那些按顺序排列的标记构成元素标记。

在POSIX字符串中
似乎您没有注意
http equiv中的
连字符

编辑 非常粗糙的正则表达式可以编写如下:

"</?\\w+((\\s+(\\w|\\w[\\w-]*\\w)(\\s*=\\s*(?:\".*?\"|'.*?'|[^'\">\\s]+))?)+\\s*|\\s*)/?>"

“在您的POSIX字符串
中,您似乎没有在
http equiv

编辑 非常粗糙的正则表达式可以编写如下:

"</?\\w+((\\s+(\\w|\\w[\\w-]*\\w)(\\s*=\\s*(?:\".*?\"|'.*?'|[^'\">\\s]+))?)+\\s*|\\s*)/?>"

“谢谢你的帮助。我想我会尽量让它不那么复杂,更多地关注标记化,而不是试图解析它。谢谢你的帮助。我想我会尽量让它不那么复杂,更多地关注标记化,而不是试图解析它。