我们有一个多线程RPC服务器来解析输入字符串.我们碰到的地方Scala的解析器组合库不是多线程安全的问题:在var lastNoSuccess Parsers.scala用于任何解析.我们在这一行中得到一个NullPointerException
if (!(lastNoSuccess != null && next.pos < lastNoSuccess.next.pos))
Run Code Online (Sandbox Code Playgroud)
通过创建扩展其中一个解析器的对象来实现解析器的默认方式,但是我想按需构造解析器,因此每个解析器都有自己的内部状态,因此我使用的是类而不是对象.但是,由于我需要对结果进行模式匹配,因此我无法编译它:
import scala.util.parsing.combinator.RegexParsers
class SqlParserImpl
extends RegexParsers
{
val term: Parser[String] = """(?i)term\b""".r
}
object Test
{
def main(args: Array[String]): Unit =
{
val parser = new SqlParserImpl
parser.parseAll(parser.term, "term") match {
// How do I match?
case SqlParserImpl#Success(result, _) => true
case SqlParserImpl#NoSuccess => false
}
}
}
Run Code Online (Sandbox Code Playgroud)
失败了
t.scala:16: error: '=>' expected but '#' found.
case SqlParserImpl#Success(result, _) => true
^
t.scala:17: error: '=>' expected but …Run Code Online (Sandbox Code Playgroud) 我对scala中的">>"有点困惑.Daniel在解析xml的Scala解析器组合器中说道?它可以用于根据先前解析器的结果参数化解析器.有人可以给我一些例子/提示吗?我已经读过scaladoc但仍然不理解它.
谢谢
我希望应用一系列nom解析器并返回&str匹配的完整内容。我想匹配表单的字符串a+bc+。使用现有的chain!宏,我可以非常接近:
named!(aaabccc <&[u8], &str>,
map_res!(
chain!(
a: take_while!(is_a) ~
tag!("b") ~
take_while!(is_c) ,
|| {a}
),
from_utf8
));
Run Code Online (Sandbox Code Playgroud)
在哪里
fn is_a(l: u8) -> bool {
match l {
b'a' => true,
_ => false,
}
}
fn is_c(l: u8) -> bool {
match l {
b'c' => true,
_ => false,
}
}
Run Code Online (Sandbox Code Playgroud)
假设我们有 'aaabccc' 作为输入。上面的解析器将匹配输入,但只会返回“aaa”。我想做的是返回原始输入“aaabccc”。
chain!不是正确的宏,但没有另一个看起来更正确的宏。最好的方法是什么?
在撰写本文时,我正在使用 nom1.2.2和 rustc 1.9.0-nightly (a1e29daf1 2016-03-25)。
考虑以下将数字字符串转换为ints的解析器:
let toInt (s:string) =
match Int32.TryParse(s) with
| (true, n) -> preturn n
| _ -> fail "Number must be below 2147483648"
let naturalNum = many1Chars digit >>= toInt <?> "natural number"
Run Code Online (Sandbox Code Playgroud)
当我在非数字字符串上运行它时,"abc"它显示正确的错误消息:
let toInt (s:string) =
match Int32.TryParse(s) with
| (true, n) -> preturn n
| _ -> fail "Number must be below 2147483648"
let naturalNum = many1Chars digit >>= toInt <?> "natural number"
Run Code Online (Sandbox Code Playgroud)
但是,当我给它一个超出int范围的数字字符串时,它会给出以下适得其反的信息:
Error in Ln: 1 Col: 1
abc …Run Code Online (Sandbox Code Playgroud) 考虑使用这些不同的解析器组合器。
import Control.Applicative.Combinators
import Text.Regex.Applicative
main :: IO ()
main = do
let parser1 = sym '"' *> manyTill anySym (sym '"')
print $ match parser1 "\"abc\""
let parser2 = sym '"' *> many anySym <* sym '"'
print $ match parser2 "\"abc\""
Run Code Online (Sandbox Code Playgroud)
import Control.Applicative.Combinators
import Text.ParserCombinators.ReadP hiding(many, manyTill)
main :: IO ()
main = do
let parser1 = char '"' *> manyTill get (char '"')
print $ readP_to_S parser1 "\"abc\""
let parser2 = char '"' *> many get <* …Run Code Online (Sandbox Code Playgroud) 我试图通过 Haskell 编写一个简单的解析器,但陷入了无限循环。代码是:
import Control.Applicative (Alternative, empty, many, (<|>))
data Parser a = Parser {runParser :: String -> [(a, String)]}
instance Functor Parser where
fmap f (Parser p) = Parser $ \s -> [(f x', s') | (x', s') <- p s]
instance Applicative Parser where
pure x = Parser $ \s -> [(x, s)]
(Parser pf) <*> (Parser p) = Parser $ \s -> [(f' x, ss') | (f', ss) <- pf s, (x, ss') <- p ss]
instance …Run Code Online (Sandbox Code Playgroud) 我试图编写一个简单的html模板引擎(为了好玩),并想解析这样的结构
A.正常行是HTML
B.如果一行开头,$则将其视为java代码行
$ if (isSuper) {
<span>Are you wearing red underwear?</span>
$ }
Run Code Online (Sandbox Code Playgroud)
C.如果${}包装多行,其中的所有代码都应该是java代码.
D.如果一行开头$include然后在线上做一些技巧(调用另一个模板)
$include anotherTemplate(id, name)
Run Code Online (Sandbox Code Playgroud)
这将创建一个新实例anotherTemplate,并调用它的render()方法
E.和将有更多的"命令"比其他$include,例如$def,$val.
如何在解析器组合器中表达这一点?实际上它是一个条件分叉
对于1.和2.,我有这样的事情:
'$' ~> ( '{' ~> upto('}') <~ '}' | not('{') <~ newline )
Run Code Online (Sandbox Code Playgroud)
其中,upto从Scalate的Scamel解析器借来的(我刚开始读,不是很了解)
我曾经not('{')将$....代码行与${...}块区分开来.但这很麻烦,不会扩展到其他"命令"
那我该怎么办呢?
对于具有关键字的语言,需要一些特殊的技巧来防止例如"if"被解释为标识符,并且"ifSomeVariableName"变为关键字"if",后跟标识符流中的标识符"SomeVariableName".
对于递归下降和Lex/Yacc,我简单地采用了在词法分析器和解析器之间转换令牌流的方法(根据有用的指令).
然而,FParsec似乎并没有真正做一个单独的词法分析步骤,所以我想知道处理这个问题的最佳方法是什么.说到,似乎Haskell的Parsec支持lexer层,但FParsec不支持?
我正在使用Scala的Parser Combinators来解析一个字符串(没有新行,人为的例子).
字符串由许多不同的部分组成,我想分别提取并填充案例类.
case class MyRecord(foo: String, bar: String, baz: String, bam: String, bat: String)
object MyParser extends scala.util.parsing.combinator.RegexParsers {
val foo: Parser[String] = "foo"
val bar: Parser[String] = "bar"
val baz: Parser[String] = "baz"
val bam: Parser[String] = "bam"
val bat: Parser[String] = "bat"
val expression: Parser[MyRecord] =
foo ~ bar ~ baz ~ bam ~ bat ^^ {
case foo ~ bar ~ baz ~ bam ~ bat => MyRecord(foo, bar, baz, bam, bat)
}
} …Run Code Online (Sandbox Code Playgroud) 猜猜这个编译的结果是什么?
import scala.util.parsing.combinator._
object ExprParser extends JavaTokenParsers {
lazy val literal = int
lazy val int = rep("0")
}
Run Code Online (Sandbox Code Playgroud)
编译器说这int是递归的并要求它的类型.我的实验说,递归的核心隐藏在文字的声明中!删除它,你会看到递归消失了!
scala ×5
f# ×2
fparsec ×2
haskell ×2
parsing ×2
attoparsec ×1
backtracking ×1
overloading ×1
overriding ×1
recursion ×1
rust ×1