我正在构建一个解析器生成器, 目前它接受自定义语法并生成一个C程序来解析文本流并生成graphviz树表示。
在我的实验中定义了样本语法,我发现在某些情况下,解析被终止,但并非所有文本输入流都被消耗掉了。 随着'被终止'我的意思是,语法中的主要规则已被评估为真。
是否应修改语法以始终使用解析器来使用所有源输入文本?
谢谢
我的用例是要完全解析的单个文本文件。 只是一个简单的语法示例:
Results: <br>
<div class="shuffle_results" id="results"></div>
<form method="post">
<?php
$count = 0;
foreach ($array as $result) :
$count++;
$shuffle_count = $count;
$shuffle_firstname = htmlentities($result['firstname']);
$shuffle_lastname = htmlentities($result['lastname']);
$shuffle_id = htmlentities($result['id']);
$shuffle_username = htmlentities($result['username']);
$shuffle_email = htmlentities($result['email']);
?>
<input type="hidden" name="count[]" value="<?php echo $shuffle_count; ?>">
<input type="hidden" name="firstname[]" value="<?php echo $shuffle_firstname; ?>">
<input type="hidden" name="lastname[]" value="<?php //echo $shuffle_lastname; ?>">
<input type="hidden" name="id[]" value="<?php echo $shuffle_id; ?>">
<input type="hidden" name="username[]" value="<?php echo $shuffle_username; ?>">
<input type="hidden" name="email[]" value="<?php echo $shuffle_email; ?>">
<?php
endforeach;
我的C解析器在123之前停止解析(不是ID)但是对主规则求值为true,并且文本输入流未完全解析。
如果我添加任意结束标记,我可以修改语法(语言)。 即
Main_rule: ID ID* ;
// ID is Terminal (a C variable token)
// Source text follows
var1 var2 123 var3
这是唯一的方法吗?
答案 0 :(得分:1)
像往常一样这样的问题,答案是“这取决于用例。”
通常,解析器将使用整个文本,但并不总是清楚“整个文本”的含义。在某些情况下,一个已解析的文本流嵌入另一个中,并且终止不是文件结束(或字符串结束)标记。
在某些情况下,通过首先提取嵌入内容,然后解析提取的字符串,可以最方便地发现嵌入内容的范围。然而,这需要扫描嵌入的串两次,并且通常存在更有效的解决方案。此外,在某些情况下,如果不对其进行标记,就无法发现嵌入内容的结尾;例如,考虑在shell表达式中解析嵌入的$(
... )
子shell。
解析嵌入式语言很复杂,并且通常不提供优雅的解决方案。使用传统的扫描仪/解析器二分法来处理并发症通常更容易,其中嵌入完全在扫描仪内处理,可能使用对另一个解析器的递归调用。在这种情况下,解析器本身不直接处理输入,扫描器负责产生“输入结束”令牌。
当然,如果在完全解析的前缀的末尾有意外的文本,则必须将其标记为错误。因此,解析器至少需要能够与其调用者通信是否已经消耗了整个输入,如果没有,则确切地说还剩下要消耗的内容。
显式的“输入结束”令牌的存在允许完全的灵活性;如果语法需要“输入结束”(生成形式为start': start END_OF_INPUT
),那么当然解析后的文本必须在输入结束时终止。然后,用户可以自由地定义不需要解析整个输入文本的语法。但灵活性是有代价的:在正常情况下,用户需要添加显式增强的开始生产,而天真的用户可能会忘记这样做。这两个模型之间的区别以bison / yacc(自动增强开始生产)与lemon为例(如果需要,用户必须提供增强的开始生产)。