Parsing 解析任意用户输入

Parsing 解析任意用户输入,parsing,user-input,Parsing,User Input,我有一个数据库,里面有来自公告栏的信息。电路板使用BB代码作为格式样式。即: 我没有格式化 这是[b]粗体[/b]文本 标记也可以[i][b]嵌套[/b] 而且筑巢可能相当丑陋 我的最终目标是将这些消息转换为一些格式良好的XML(这里没有讨论;)。我不想使用正则表达式,因为正则表达式在某一点上会失败(事实上,它确实会失败) 第一步:将消息解析为某种内部表示(图形、树等)。我被困在这一点上。实际提取并没有那么大的问题,但存储是 如何将这种标记表示为某种有意义的结构。我的问题似乎与浏览器从HTM

我有一个数据库,里面有来自公告栏的信息。电路板使用BB代码作为格式样式。即:

  • 我没有格式化
  • 这是[b]粗体[/b]文本
  • 标记也可以[i][b]嵌套[/b]
  • 而且筑巢可能相当丑陋
我的最终目标是将这些消息转换为一些格式良好的XML(这里没有讨论;)。我不想使用正则表达式,因为正则表达式在某一点上会失败(事实上,它确实会失败)

第一步:将消息解析为某种内部表示(图形、树等)。我被困在这一点上。实际提取并没有那么大的问题,但存储是

如何将这种标记表示为某种有意义的结构。我的问题似乎与浏览器从HTML文件构建DOM类似(或几乎相同)。所以我认为有一些策略可以解决这个问题。我知道这个解决方案并不完美,但我愿意投入大量的时间尽可能做到最好

问题:你有什么建议/提示/意见吗?你能推荐一些文章或论文吗?还是一本讨论这些话题的书?我非常感谢您的任何意见

而且筑巢可能相当丑陋 我已经编写了一个解析器,它与您希望做的非常相似,只是它会在您的第四个示例中抛出一个错误。类似于“在[i]内意外结束标记[/b]的内容”

我认为您想要做的是非常可行的,但在内部,您将希望创建一棵树,就像您的原始文本是:

“而[b]嵌套[i]可能相当丑陋”
。(如果您以后不需要将其转换为XML,我认为这是不必要的。如果不需要转换为XML,您可以保留一个文本节的链接列表,其中每个节都标记有其格式组合)

我想到了解决这个问题的两种可能的方法(当然可能有更好的方法)。1) 预处理并在必要时插入缺少的结束和开始标记。2) 构建解析树,如果存在重叠的标记,则根据当前上下文暗示缺少的标记。我认为方法(2)会更简单、更干净

您可以基于复合模式对树进行建模,其中有一个AbstractElement类、一个扩展AbstractElement的TextElement类和一个扩展AbstractElement并包含AbstractElement类型子元素列表的标记类

首先创建一个根标记实例。然后调用rootTag.parse(text)。您需要一个扫描仪,它可以返回3种类型的标记:文本、开始标记和结束标记。扫描仪将允许您将令牌推送到它上面,它将在任何正常扫描令牌之前返回。这将允许您在遇到并处理意外的结束标记后推送新的开始标记标记。您还必须知道何时完成输入。我将使用第四种令牌类型

/* methods within class Tag */ public void parse(String text) { MyScanner scanner = new MyScanner(text); parse(scanner); } /* returns next token */ private Token parse(MyScanner scanner) { Token firstToken = scanner.getNextToken(); return parse(scanner,firstToken); } private Token parse(MyScanner scanner) { Token firstToken = scanner.getNextToken(); return parse(scanner,firstToken); } private Token parse(MyScanner scanner, Token token) { while (!token.isDone() && !token.isEndTag()) { if (token.isStartTag()) { Tag subTag = new Tag(token.getValue()); token = scanner.getNextToken(); token = subTag.parse(scanner,token); addElement(subTag); } else { TextElement text = new TextElement(token.getValue()); addElement(text); token = scanner.getNextToken(); } } if (token.isEndTag()) { if (!token.getValue().equals(getName()) { scanner.push(new Token(Token.START_TAG,token.getValue())); } else { token = scanner.getNextToken(); } } return token; } /*类标记中的方法*/ 公共void解析(字符串文本){ MyScanner scanner=新的MyScanner(文本); 解析(扫描器); } /*返回下一个令牌*/ 专用令牌解析(MyScanner扫描程序){ Token firstToken=scanner.getNextToken(); 返回解析(scanner,firstToken); } 专用令牌解析(MyScanner扫描程序){ Token firstToken=scanner.getNextToken(); 返回解析(scanner,firstToken); } 专用令牌解析(MyScanner扫描程序、令牌){ 而(!token.isDone()&&!token.isEndTag()){ if(token.isStartTag()){ Tag subTag=新标记(token.getValue()); 令牌=scanner.getNextToken(); token=subTag.parse(扫描器,token); 附加元素(子标记); } 否则{ TextElement text=新的TextElement(token.getValue()); 增编(文本); 令牌=scanner.getNextToken(); } } 如果(token.isEndTag()){ 如果(!token.getValue().equals(getName()){ push(新令牌(Token.START_标记,Token.getValue()); } 否则{ 令牌=scanner.getNextToken(); } } 返回令牌; } 因此,如果要解析“并且[b]嵌套[i]可能相当丑陋”,那么应该创建以下内容

rootTag.parse should be adding: TextElement: "And the " Tag: "b" TextElement: "nesting " Tag: "i" TextElement: "can be" (... at this point the odd [/b] is encountered ...) (... push "i" start tag on the scanner ...) (... here the [/b] is encountered (again) ...) Tag: "i" (this was scanned because it had been pushed to the scanner) TextElement: " rather" TextElement: " ugly" rootTag.parse应添加: TextElement:“和” 标签:“b” TextElement:“嵌套” 标签:“我” TextElement:“可以” (…此时遇到了奇怪的[/b]。) (…按下扫描仪上的“i”开始标签…) (…这里遇到了[/b]。) 标签:“i”(这是扫描的,因为它被推到了扫描仪上) TextElement:“相当” TextElement:“丑陋”
注意:在文本区域中进行编码不利于测试和调试。请接受此答案作为提示或可能性,而不是您定义的答案。

Wow。非常感谢。您的示例代码几乎解决了我的所有问题:)谢谢您,祝您好运。我刚刚修正了一个输入错误,我在push调用中传递了错误的参数,现在也修正了。