我正在尝试使用解析器组合器,我经常遇到无限递归.这是我遇到的第一个:
import util.parsing.combinator.Parsers
import util.parsing.input.CharSequenceReader
class CombinatorParserTest extends Parsers {
type Elem = Char
def notComma = elem("not comma", _ != ',')
def notEndLine = elem("not end line", x => x != '\r' && x != '\n')
def text = rep(notComma | notEndLine)
}
object CombinatorParserTest {
def main(args:Array[String]): Unit = {
val p = new CombinatorParserTest()
val r = p.text(new CharSequenceReader(","))
// does not get here
println(r)
}
}
Run Code Online (Sandbox Code Playgroud)
如何打印正在发生的事情?为什么没有完成?
我编写了一个基于Scala解析器组合器的解析器:
class SxmlParser extends RegexParsers with ImplicitConversions with PackratParsers {
[...]
lazy val document: PackratParser[AstNodeDocument] =
((procinst | element | comment | cdata | whitespace | text)*) ^^ {
AstNodeDocument(_)
}
[...]
}
object SxmlParser {
def parse(text: String): AstNodeDocument = {
var ast = AstNodeDocument()
val parser = new SxmlParser()
val result = parser.parseAll(parser.document, new CharArrayReader(text.toArray))
result match {
case parser.Success(x, _) => ast = x
case parser.NoSuccess(err, next) => {
tool.die("failed to parse SXML input " +
"(line …Run Code Online (Sandbox Code Playgroud) 我有一个值列表,我可以从中构建一个解析器列表,它通过映射依赖于这些值(参见示例).那么我想要做的是通过连接将解析器列表转换为单个解析器.
一种可能性是使用foldLeft和~:
parsers.foldLeft(success(Nil)){case (ps,p) => rs ~ p ^^ {case xs ~ x => x ::xs}} ^^ (_.reverse)
Run Code Online (Sandbox Code Playgroud)
我不知道组合器解析器是如何工作的; 会有一个深度为列表长度的调用堆栈吗?因此,我可能会遇到SO错误很长时间的连接?
有不同的方式更具可读性吗?
假设您有一个包含两行的文件.第一行包含n个整数x_1到x_n.第二行包含根据第一行属于组的x_1 + x_2 + ... x_n整数.我想从第一行获取整数序列并创建n个解析器p_1到p_n,其中p_i解析x_i整数.
假设我有l = List(1,2,3)第一行的整数列表.对于每个整数,n我创建一个解析n整数的解析器:parsers = l.map(repN(_,integer)).
我正在研究一种需要考虑运算符优先级的解析逻辑.我的需求并不太复杂.首先,我需要乘法和除法,以获得比加法和减法更高的优先级.
例如:1 + 2*3应视为1 +(2*3).这是一个简单的例子,但你明白了!
[我还需要添加几个自定义令牌才能添加到优先级逻辑中,我可以根据我在此处收到的建议添加这些令牌.]
以下是处理运算符优先级的一个示例:http://jim-mcbeath.blogspot.com/2008/09/scala-parser-combinators.html#precedencerevisited.
还有其他想法吗?
有没有一种方便的方法来使用Scala的解析器组合器来解析缩进很重要的语言?(例如Python)
我正在尝试使用Idris实现总解析器,基于本文.首先,我尝试实现更基本的识别器类型P:
Tok : Type
Tok = Char
mutual
data P : Bool -> Type where
fail : P False
empty : P True
sat : (Tok -> Bool) -> P False
(<|>) : P n -> P m -> P (n || m)
(.) : LazyP m n -> LazyP n m -> P (n && m)
nonempty : P n -> P False
cast : (n = m) -> P n -> P m
LazyP …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用Trifecta来解析一个非常简单的函数式语言,使用类似Haskell的布局语法.我正在处理Haddock文档和我对Parsec的经验,因为我找不到关于Trifecta本身的任何介绍性材料.
我遇到的问题是使用布局的东西,因为即使是Haddock文档也没有多大帮助.
给出以下代码:
import Text.Trifecta
import Text.Trifecta.Parser.Token.Style
import Text.Trifecta.Parser.Identifier.Style
import Text.Trifecta.Layout.Combinators
import Text.Trifecta.Language.Prim
import Control.Applicative
import Control.Monad.Trans
import Data.Maybe (fromMaybe)
import Data.HashSet as HashSet
import Data.ByteString.UTF8 as UTF8
-- Copypasta from Text.Trifecta.Parser.Identifier.Style
set :: [String] -> HashSet ByteString
set = HashSet.fromList . fmap UTF8.fromString
lang :: MonadParser m => LanguageDef m
lang = LanguageDef{ languageCommentStyle = haskellCommentStyle
, languageIdentifierStyle = emptyIdents{ styleReserved = set keywords }
, languageOperatorStyle = emptyOps{ styleReserved = set ops }
}
where
keywords = ["where"] …Run Code Online (Sandbox Code Playgroud) 我正在尝试从头启动C(的子集),而不使用额外的依赖项(解析器生成器,库等)。我也想利用解析器组合器的思想,这在函数式编程中是一种很棒的技术。我想以一种简洁实用的方式将这种想法从功能世界借鉴到过程C中。
我尝试为以下玩具语法实现一些必要的解析器组合器,这也是Simon Peyton Jones 的《实现功能语言-教程》一书中的示例。
greeting -> hg person "!"
hg -> "hello"
| "goodbye"
Run Code Online (Sandbox Code Playgroud)
person以字母开头的令牌在哪里?例如,令牌列表
["goodbye", "James", "!"]
Run Code Online (Sandbox Code Playgroud)
被解析为
[(("goodbye", "James"), ["!"])]
Run Code Online (Sandbox Code Playgroud)
(这本书使用了Haskell,很难使它与语言无关,但是您会明白的:-)
我用C语言实现了这一点,您可以在这里查看代码:https : //gist.github.com/4451478
此实现花费200多行C代码,远远超过本书中编写的约20行Haskell。因此,我不确定我是否在使用C进行解析器组合器方面是否正确,以及是否有任何可能的改进。任何建议都欢迎。提前致谢。
我正在使用Trifecta解析器组合库,我的解析器输出AST数据类型的实例.我希望每个实例都有唯一的ID(简单的Int).
在Parsec中,我会创建自定义状态并在neccesery时递增ID.我们怎样才能在Trifecta中做到这一点?
在设计scala解析器组合器时,有人可以解释如何以及何时使用三重插入符^^^(与双插入符^^)?以及何时/如何使用parser.into()方法(>>).