Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Parsing 解析可选递归解析器在无限递归中运行_Parsing_Haskell_Megaparsec - Fatal编程技术网

Parsing 解析可选递归解析器在无限递归中运行

Parsing 解析可选递归解析器在无限递归中运行,parsing,haskell,megaparsec,Parsing,Haskell,Megaparsec,我目前正在为ECMAScript 5编写一个解析器(作为玩具)。该标准规定了应如何解析逻辑或表达式: <LogicalORExpression> : <LogicalANDExpression> <LogicalORExpression> || <LogicalANDExpression> : || 基本上这相当于 =[||] 但是我应该如何解析它而不陷入一个infite循环呢?我当前的解析器显然做到了: logicalOrE

我目前正在为ECMAScript 5编写一个解析器(作为玩具)。该标准规定了应如何解析逻辑或表达式:

<LogicalORExpression> :
    <LogicalANDExpression>
    <LogicalORExpression> || <LogicalANDExpression>
:
|| 
基本上这相当于

=[||]

但是我应该如何解析它而不陷入一个infite循环呢?我当前的解析器显然做到了:

logicalOrExpression :: Parser LogicalOrExpression
logicalOrExpression = do
    orExpr <- optional $ do
        e <- logicalOrExpression
        _ <- symbol "||"
        return e
    andExpr <- logicalAndExpression
    case orExpr of
        Just e -> return $ LogicalOrExpression (e, andExpr)
        Nothing -> return $ AndExpression andExpr
logicalOrExpression::解析器logicalOrExpression
logicalOrExpression=do

orExpr空字符串与这个解析器匹配,我相信它会导致Magaparsec中的无限递归。我认为你的函数中缺少了一个“术语”或“布尔值”。如果我写
True | | False
什么会捕获第一个“True”

空字符串与这个解析器匹配,我相信它会导致Magaparsec中的无限递归。我认为你的函数中缺少了一个“术语”或“布尔值”。如果我写的是
True | | False
语法中第一个与之等价的“True”

<LogicalORExpression> :
    <LogicalANDExpression>
    <LogicalANDExpression> || <LogicalORExpression>
:
|| 
变成

<LogicalORExpression> :
    <LogicalANDExpression> [|| <LogicalORExpression>]
:
[|| ]

一般来说,如果可能的话,你需要以LL(1)的形式重写语法

那个语法看起来相当于

<LogicalORExpression> :
    <LogicalANDExpression>
    <LogicalANDExpression> || <LogicalORExpression>
:
|| 
变成

<LogicalORExpression> :
    <LogicalANDExpression> [|| <LogicalORExpression>]
:
[|| ]
一般来说,如果可能的话,你需要以LL(1)的形式重写语法

如果需要解析具有优先级和关联性的运算符语法,那么它最容易使用

expr = makeExprParser term table
    where
        term = literal <|> parenthesised expr
        table = [[InfixL (string "&&" $> And)], [InfixL (string "||" $> Or)]]
expr=makeExprParser术语表
哪里
术语=带括号的文字表达式
表=[[InfixL(字符串“&&“$>和)],[InfixL(字符串“| |“$>或)]]
对于
literal
和带括号的
的合适定义,这将解析由左关联中缀
&
|
运算符组成的literal表达式语法,其中
&
具有比
|
更高的优先级。Megaparsec负责生成LL(k)解析器的繁琐工作,并生成正确(本例中为左关联)的解析树

当然,JavaScript的表达式语法要比两个运算符大得多。这个例子可以直接扩展到包含(例如)一元前缀操作符,比如
、后缀函数调用等。请参阅。

如果需要解析具有优先级和关联性的运算符语法,则最容易使用

expr = makeExprParser term table
    where
        term = literal <|> parenthesised expr
        table = [[InfixL (string "&&" $> And)], [InfixL (string "||" $> Or)]]
expr=makeExprParser术语表
哪里
术语=带括号的文字表达式
表=[[InfixL(字符串“&&“$>和)],[InfixL(字符串“| |“$>或)]]
对于
literal
和带括号的
的合适定义,这将解析由左关联中缀
&
|
运算符组成的literal表达式语法,其中
&
具有比
|
更高的优先级。Megaparsec负责生成LL(k)解析器的繁琐工作,并生成正确(本例中为左关联)的解析树


当然,JavaScript的表达式语法要比两个运算符大得多。这个例子可以直接扩展到包含(例如)一元前缀操作符,比如
、后缀函数调用等。请参阅。

由于我希望在生成的AST方面遵守规范,我决定切换到基于Earley的解析器,而不是解析器组合器,因为Earley的算法可以处理左递归


如果我可以将语法扁平化,我会使用Benjamin Hodgson的答案,因为我想在生成的AST方面忠实于规范,所以我决定切换到基于Earley的解析器,而不是解析器组合器,因为Earley的算法可以处理左递归


如果我可以将语法展平,我会使用Benjamin Hodgson的答案

No这两个词是不等价的,因为这会改变操作符的关联性AFAICT@SuperManitu没错。如果您需要原始的,我想您必须对AST进行后处理。左递归在LL(1)解析器中不可行。您也可以尝试
sepBy1
,它会给您一个列表,然后您可以在生成AST之前根据自己的意愿进行关联。是的,我认为您是对的,将语法转换为正确的递归语法,然后调整AST。不,这两者是不等价的,因为这会改变操作符的关联性AFAICT@SuperManitu没错。如果您需要原始的,我想您必须对AST进行后处理。左递归在LL(1)解析器中不可行。您也可以尝试
sepBy1
,它会给您一个列表,然后您可以在生成AST之前根据自己的意愿进行关联。是的,我认为您是对的,将语法转换为正确的递归语法,然后调整AST。这个可选部分的全部要点是最终不解析任何东西。如果我在修复递归的同时添加任何消耗字符,它也不会再接受所有有效字符串,但必须先获取一些内容,否则将永远成功,而不会取得进展。你所拥有的是,“一个logicalOrExpression是一个logicalOrExpression,它是一个logicalOrExpression,它是一个logicalOrExpression,它是一个logicalOrExpression…”可选部分的全部要点是最终不解析任何东西。如果我在修复递归的同时添加任何消耗字符,它也不会再接受所有有效字符串,但必须先获取一些内容,否则将永远成功,而不会取得进展。你有的是,“一个logicalOrExpression是一个logicalOrExpression,它是一个logicalOrExpression,它是一个logicalOrExpression,它是一个logicalOrExpression…”logicalOrExpression=sepBy1(symbol“| |”)logicalOrExpression
logicalOrExpression=sepBy1(symbol“| | |”)logicalOrExpression
,但问题是,这将把语法简化为一个单一的语法