Javascript 递归下降解析器应该在重复的字母终端上出错
主要问题:如何更新命题逻辑的递归下降解析器(用JavaScript编写),使“p~”和“pp”等字符串返回“无效”消息 我对HTML、JavaScript和解析非常陌生。我想看看我是否能够制作一个简单的网页,可以解析命题逻辑中的简单公式。以下是语法:Javascript 递归下降解析器应该在重复的字母终端上出错,javascript,parsing,recursive-descent,propositional-calculus,Javascript,Parsing,Recursive Descent,Propositional Calculus,主要问题:如何更新命题逻辑的递归下降解析器(用JavaScript编写),使“p~”和“pp”等字符串返回“无效”消息 我对HTML、JavaScript和解析非常陌生。我想看看我是否能够制作一个简单的网页,可以解析命题逻辑中的简单公式。以下是语法: <formula> ::= <unaryconnective> <formula> | "(" <formula> <binaryconnective> <f
<formula> ::= <unaryconnective> <formula>
| "(" <formula> <binaryconnective> <formula> ")"
| <proposition>
<unaryconnective> ::= "~"
<binaryconnective> ::= "&"
<proposition> ::= "p"
| "q"
| "r"
但是,当它应该返回“无效”时,它错误地为这些字符串返回“有效”:
在这些情况下,解析器似乎不检查整个字符串,只检查第一个字母前的字符和字母本身,因此认为可以。我尝试在“else if(命题(sym)”中的公式()中添加某种验证部分以确保字母后面的字符是有效的,但这不起作用,因为有效字符会根据字母前面的字符而变化。更改语法可能会有所帮助。我不太明白在创建这些语法时应该考虑什么,除了左递归会给递归de带来麻烦我研究了几个关于递归下降解析器的堆栈溢出问题,但没有一个能帮助我解决这个问题
我如何更新我的解析器,以便这样的字符串返回“无效”的结果?我不一定要寻找一个完整的答案,只是一些指针上的事情要考虑或资源要看。如果你还知道一个好的资源,在建设语法时要考虑什么(尤其是参考解析器),那太好了
注意:我的解析器目前不处理空白。目前我对此没有意见,因为我主要关心的是在更新内容以处理空白之前,如何正确地进行其他解析。我没有对您的代码进行过深入研究,但我的印象是: 您的解析器正在检查它看到的第一组字符是否构成有效的公式,然后停止。如果垃圾随后出现,则无所谓,您的解析器仍然很高兴,因为它找到了有效的公式 我在你的语法中看到了两种处理方法:
- 要求公式以某些“流结束”元字符结尾
- 添加与一系列公式匹配的新规则
我发现这个分支没有返回任何东西是可疑的。你好,JETM。谢谢你的回答。我更新了你提到的分支,所以它返回了一些东西。你对我遇到的问题的看法是正确的。我不希望出现“流末”字符,因为我希望能够输入一个类似于逻辑教科书中的字符串,而这些字符串没有这样的字符。我不理解你的第二个建议。新规则被放在递归的一边,在我看来,添加规则会使字符串像“pp”有效,这不是我想要的。但我完全可能误解了新的建议规则。@Zachary您不必修改输入字符串。您只需让您的lexer在输入结束时发出一个特殊标记即可。
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<title>Logic App</title>
<script type="text/javascript">
var sentence;
var len;
var i;
var sym;
function validate() {
var result;
sentence = document.getElementById('formulaentry').value;
len = sentence.length;
i = -1;
if (sentence == "") {
document.getElementById('formulaentry').value = "There's no formula!";
} else {
nextSym();
result = formula();
if(result == 0) {
document.getElementById('formulaentry').value = "Invalid";
} else {
document.getElementById('formulaentry').value = "Valid";
}
}
}
function nextSym() {
i++;
if (i <= (len-1)) {
sym = sentence.charAt(i);
} else {
sym = "";
}
//console.log("Current Sym:" + sym);
}
function accept(s) {
if (sym == s) {
nextSym();
return 1;
}
return 0;
}
function expect(s) {
if (accept(s)) {
return 1;
}
return 0;
}
function formula() {
if (unaryconn(sym)) {
nextSym();
if (formula() == 0) return 0;
return 1;
} else if (accept("(")) {
if (formula() == 0) return 0;
if (binaryconn(sym) == 0) return 0;
nextSym();
if (formula() == 0) return 0;
if (!expect(")")) return 0;
return 1;
} else if (proposition(sym)) {
nextSym();
return 1;
} else {
return 0;
}
}
function unaryconn(s) {
if (s == "~") {
return 1;
} else {
return 0;
}
}
function binaryconn(s) {
if (s == "&") {
return 1;
} else {
return 0;
}
}
function proposition(s) {
if (s == "p" || s == "q" || s == "r") {
return 1;
} else {
return 0;
}
}
</script>
</head>
<body>
<h1>Logic App</h1>
<h2>Check if formula is well-formed:</h2>
<p>Enter a formula into the text box and click "Validate" to see if it is a
wff.</p>
<form id='frmValidateFormula'>
<p>
<input
type='text'
id='formulaentry'
placeholder='Input formula here'>
</p>
<p>
<input
type='button'
id='btnValidate'
value='Validate'
onclick='validate()'>
</p>
</form>
</body>
</html>
p
~p
(p&p)
~(p&p)
(~(p&~~p)&(~p&~p))
p~
pp
~p~
p&
p(
p)
ppqqpqpq
<document> ::= <formula> |
<formula> <document>
} else if (proposition(sym)) {
nextSym();
}