2

我正在构建一个简单的解析器,但我很难理解一般设计。最佳做法是什么?

解析器获取一个简单的文本文件并将其构造成一个 HTML 文件,该文件将大量使用嵌套列表并为每个列表项添加一个索引和一个 ID。

输入(为清楚起见添加了缩进)。

A. 随机名称的第一部分
  第1条
  垃圾邮件和鸡蛋等等
  第二条
    1.第一个成员
    2.第二个成员
    3.最终成员
B. 第二部分叫什么
  第三条
  这个没有成员,但它确实包含潜艇
    一个。第 1 项
    湾。第 2 项
  第四条
    1. 会员
    2. 有subs的成员
      一个。子 1 在这里
      湾。子2在这里
      C。最后的子
C. 另一部分
ETC

我有正则表达式来查找带有行号的各种列表项(现在我正在使用词法分析器,但这可能有点矫枉过正,对吧?)

正如我所说,我需要制作嵌套的 HTML 列表,每个列表项都有一个 ID。根据您的经验,您将如何表示文档的结构?

作为一系列元组或字典,每个项目都有( id , line-number ):

list_section = ( ('A',1), ('B',8), ('C',18), ... )
list_article = ( ('1',2), ('2',4), ('3',9), ('4',13), ... )
list_member = ( ('2-1',5), ('2-2',6), ('2-3',7), ('4-1',14), ...)
etc

或者作为嵌套元组,每个标记都有( TYPE , id , line-number ):

(('SECTION','A',1 , 
    ('ARTICLE','1',2),
    ('ARTICLE','2',4 ,
        ('MEMBER','2-1',5),
        ('MEMBER','2-2',6),
        ('MEMBER','2-3',7)
    )
 )

现在我倾向于第二种选择。第一个将更容易构建和迭代,但层次结构只能通过查看周围的行号来推断。

你会这样做,还是完全不同的方式?我不是要你写我的解析器或正则表达式,我只是在寻找关于最佳实践的合理建议。

我在 HTML 中添加了所需的输出。指数:

<div id="index">
    <ol class="indexlist sections">
        <li><a href="#listref_A">First section with random name</a><br>
            Article 1 - 2</li>
        <li><a href="#listref_B">Second section called whatever</a><br>
            Artikel 3 - 4</li>
        <li><a href="#listref_C">Another section</a><br>
            Article 5</li>
    </ol>

和内容:

<div id="content">
    <ol class="sections">
        <li id="listref_D"><h2></h2>
        <ol class="articles">
            <li id="listref_8">Article 8
                <ol class="members">
                    <li id="listref_8-1">Member 1.</li>
                    <li id="listref_8-2">Member 2</li>
                    <li id="listref_8-3">Member 3</li>
                    <li id="listref_8-4">Member 4.</li>
                </ol>
            </li>
        </ol>
    </li>
    <li id="listref_E">Section E
        <ol class="articles">
            <li id="listref_9">Article 9
                <ol class="members">
                    <li id="listref_9-1">Member 1 has subs:
                        <ol class="subs">
                            <li id="listref_9-1-a">sub a;</li>
                            <li id="listref_9-1-b">sub b;</li>
                            <li id="listref_9-1-c">sub c.</li>
                        </ol>
                    </li>
                    <li id="lijstref_9-2">Member 2, refers to <a href="#listref_8-2">article 8 sub 2</a>.</li>
                </ol>
4

1 回答 1

2

尝试 ANTLR Lexer/Parser 组合。您所需要的只是生成词法分析器/基本解析器组合的正则表达式。它使用类似于 BNF 语法的策略,您可以非常轻松地定义操作以打印到控制台或文件。它默认输出 Java,但 ANTLR 4 也输出到 C#。ANTLR 3 可以输出到更多的语言,例如 Ruby。

要生成词法分析器的一部分,您可能会执行类似的操作

 // Define Tokens
 WS : [ \t\r\n] ~> skip;
 DOT : '.';
 ARTICLE : 'Article';

 fragment DIGIT : [0-9];
 fragment ALPHA : [a-zA-Z];

 AlphaString : ALPHA+;
 Number : DIGIT+;
 AlphaNumericString : (AlphaString | Number)+;

 // Define Lexer and Parser Grammars
 SectionTitle : AlphaString;
 SectionHeader : SectionTitle DOT AlphaNumericString;

 ArticleHeader : ARTICLE Number;

 MemberTitle : Number;
 MemberHeader : MemberTitle DOT AlphaNumericString;

 submember : /*Code to define submember*/;     

 member : MemberHeader submember+;

 article : ArticleHeader (member | AlphaNumericString)+;

 section : SectionHeader
           (article | AlphaNumericString)+;

显然这不是一个全面的语法,但它显示了基础知识。一个很好的参考是ANTLR 4 Documentation WikiANTLR 4: The Defenitive Guide。这些向您展示了如何执行这些语法以及如何在其中嵌入操作。对于小型或大型项目,它们都是很好的指南。后者的第 2 章和第 3 章通过很好的示例以简单的方式展示了您需要的基础知识。

于 2013-12-30T22:56:22.213 回答