我正在尝试使用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进行解析器组合器方面是否正确,以及是否有任何可能的改进。任何建议都欢迎。提前致谢。
问题
我今天遇到了一个问题,我不知道如何解决它.这对我来说很奇怪,因为我写的代码应该(根据我目前的知识)是正确的.
所以下面你可以找到一个示例解析器组合器.最重要的是pOperator,它以非常简单的方式(仅用于演示目的)构建运算符AST.它消耗"x"并且可以消耗由空格分隔的多个"x".
我也有pParenscombinator,定义如下:
pPacked pParenL (pWSpaces *> pParenR)
Run Code Online (Sandbox Code Playgroud)
所以它在关闭括号之前消耗空格.
样本输入/输出
正确的输入/输出应该是:
in: "(x)"
out: Single "x"
in: "(x )"
out: Single "x"
Run Code Online (Sandbox Code Playgroud)
但我得到了:
in: "(x)"
out: Single "x"
in: "(x )"
out: Multi (Single "x") (Single "x")
-- Correcting steps:
-- Inserted 'x' at position LineColPos 0 3 3 expecting one of ['\t', ' ', 'x']
Run Code Online (Sandbox Code Playgroud)
但是在第二个例子中我得到了错误 - 解析器的行为就像它贪婪地吃了一些令牌(而且没有贪婪的操作).
我会感谢任何帮助.
示例代码
import Prelude hiding(lex)
import Data.Char hiding (Space)
import qualified Text.ParserCombinators.UU as UU
import Text.ParserCombinators.UU …Run Code Online (Sandbox Code Playgroud) 我正在使用Trifecta解析器组合库,我的解析器输出AST数据类型的实例.我希望每个实例都有唯一的ID(简单的Int).
在Parsec中,我会创建自定义状态并在neccesery时递增ID.我们怎样才能在Trifecta中做到这一点?
在设计scala解析器组合器时,有人可以解释如何以及何时使用三重插入符^^^(与双插入符^^)?以及何时/如何使用parser.into()方法(>>).
我正在看这个图书馆,那里没有多少文档:https : //pythonhosted.org/parsec/#examples
我知道还有其他选择,但我想使用这个库。
我想解析以下字符串:
mystr = """
<kv>
key1: "string"
key2: 1.00005
key3: [1,2,3]
</kv>
<csv>
date,windspeed,direction
20190805,22,NNW
20190805,23,NW
20190805,20,NE
</csv>"""
Run Code Online (Sandbox Code Playgroud)
虽然我想解析整个事情,但我只想抓住<tags>。我有:
>>> import parsec
>>> tag_start = parsec.Parser(lambda x: x == "<")
>>> tag_end = parsec.Parser(lambda x: x == ">")
>>> tag_name = parsec.Parser(parsec.Parser.compose(parsec.many1, parsec.letter))
>>> tag_open = parsec.Parser(parsec.Parser.joint(tag_start, tag_name, tag_end))
Run Code Online (Sandbox Code Playgroud)
好,看起来不错 现在使用它:
>>> tag_open.parse(mystr)
Traceback (most recent call last):
...
TypeError: <lambda>() takes 1 positional argument but 2 were given
Run Code Online (Sandbox Code Playgroud)
这失败了。恐怕我什至不明白我的lambda表达式给出两个参数的含义,这很明显是1.如何进行?
对于所有奖励积分,我的最佳期望输出是: …
我parsimmon用来解析一个简单的数学表达式,但我无法解析一个遵循操作顺序的简单数学表达式(即*/优先级高于+-)。
即使你不熟悉这个库,也请帮助我解决没有左递归和无限递归的优先级问题。
谢谢你。
我使用了打字稿:
"use strict";
// Run me with Node to see my output!
import * as P from "parsimmon";
import {Parser} from "parsimmon";
// @ts-ignore
import util from "util";
///////////////////////////////////////////////////////////////////////
// Use the JSON standard's definition of whitespace rather than Parsimmon's.
let whitespace = P.regexp(/\s*/m);
// JSON is pretty relaxed about whitespace, so let's make it easy to ignore
// after most text.
function token(parser: Parser<string>) {
return parser.skip(whitespace);
}
// Several …Run Code Online (Sandbox Code Playgroud) /* ... */使用Scala解析器组合器(有效)解析C风格的多行注释(即)的最佳方法是什么?
在我参与的项目中,我们解析了类似C语言的编程语言,并希望支持多行注释.我们使用的子类StandardTokenParsers已经处理了这样的注释(通过StdLexical.但是,该类仅适用于相当短的多行注释,否则会耗尽堆栈空间.
我们还尝试提供我们自己的空白定义,以提高效率.我们使用了RegexParser(受StackOverflow上的另一个问题的启发)如下:
class Parser extends StandardTokenParsers {
override val lexical = new StdLexical {
def rp: RegexParsers = new RegexParsers {}
override val whitespace: Parser[Any] = rp.regex("""(\s|//.*|(?m)/\*(\*(?!/)|[^*])*\*/)*""".r).asInstanceOf[Parser[Any]]
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
这略微改善了这种情况,但如果评论超过几十行,仍会导致堆栈溢出.任何想法如何改善这个?
我在scala中为我的解析器编写了一个新的组合子.
它是^^组合子的变体,它传递位置信息.但访问输入元素的位置信息确实是性价比.
在我的情况下,解析一个大的例子需要大约3秒没有位置信息,它需要超过30秒.
我编写了一个可运行的示例,其中运行时在访问位置时大约多50%.
这是为什么?我怎样才能获得更好的运行时间?
例:
import scala.util.parsing.combinator.RegexParsers
import scala.util.parsing.combinator.Parsers
import scala.util.matching.Regex
import scala.language.implicitConversions
object FooParser extends RegexParsers with Parsers {
var withPosInfo = false
def b: Parser[String] = regexB("""[a-z]+""".r) ^^@ { case (b, x) => b + " ::" + x.toString }
def regexB(p: Regex): BParser[String] = new BParser(regex(p))
class BParser[T](p: Parser[T]) {
def ^^@[U](f: ((Int, Int), T) => U): Parser[U] = Parser { in =>
val source = in.source
val offset = in.offset
val start = handleWhiteSpace(source, offset) …Run Code Online (Sandbox Code Playgroud) parsing ×6
scala ×4
haskell ×3
parsec ×2
trifecta ×2
c ×1
javascript ×1
monads ×1
performance ×1
python ×1
typescript ×1