我正在尝试lex(然后解析)一个C语言.在C中有预处理器指令,其中换行符很重要,然后是实际代码,它们只是空格.
执行此操作的一种方法是执行像早期C编译器这样的双通过程 - 为#指令设置单独的预处理器,然后将其输出调整为lex.
但是,我想知道是否可以在一个词法分析器中完成它.我很高兴编写scala解析器 - 组合器代码,但我不太确定如何StdLexical处理空格.
有人可以写一些简单的示例代码,这些代码可以说是#include一行(使用换行符)和一些简单的代码(忽略换行符)?或者这是不可能的,最好选择2-pass appproach?
试用一个简单的解析器组合器,我遇到了编译错误.
我想解析一下 - "Smith,Joe"进入Name对象,如Name(Joe,Smith).我想这很简单.
这是与之相关的代码:
import util.parsing.combinator._
class NameParser extends JavaTokenParsers {
lazy val name: Parser[Name] =
lastName <~ "," ~> firstName ^^ {case (l ~ f) => Name(f, l)}
lazy val lastName = stringLiteral
lazy val firstName = stringLiteral
}
case class Name(firstName:String, lastName: String)
Run Code Online (Sandbox Code Playgroud)
我正在测试它
object NameParserTest {
def main(args: Array[String]) {
val parser = new NameParser()
println(parser.parseAll(parser.name, "Schmo, Joe"))
}
}
Run Code Online (Sandbox Code Playgroud)
获取编译错误:
error: constructor cannot be instantiated to expected type;
found : NameParser.this.~[a,b]
required: java.lang.String
lazy val …Run Code Online (Sandbox Code Playgroud) 我刚学习Scala解析器组合库.我已经尝试了一个工作解析器,它使用抽象语法树解析一些算术表达式.所以我打电话的时候
phrase(expr)(tokens)
Run Code Online (Sandbox Code Playgroud)
我的解析器解析所有输入然后给我一个评估.但是我怎么能逐步评估呢?
说
3 + 4*7
它打印
3 + 28
然后
31
在单独的行中.
我已经扫描了api,但那里的文档并不是很有帮助...感谢您的帮助.
我发现的解析器组合器的材料包括构建复杂的解析器虽然组合,但我想知道是否有任何好的方法来通过调整库的组合解析器来定义解析器而不完全复制原始库的逻辑.
例如,这是在Real world Haskell中定义的简化CSV解析器
import Text.ParserCombinators.Parsec
csvFile = endBy line eol
line = sepBy cell (char ',')
cell = many (noneOf ",\n")
eol = char '\n'
Run Code Online (Sandbox Code Playgroud)
假设csvFile在一个库中定义,另一个库是否可以使用自定义版本的cell解析器创建自己的CSV解析器,而不必重写line和csvFile解析器?可以重写源库以使其成为可能吗?这对于CSV解析器来说非常简单,但我对广泛适用的解决方案感兴趣.
该FastParse解析器组合子Scala库给你的.rep(n)"重复"的方法,让您创建一个新的解析器,试图解析givenParser n 或更多次.如果我想完全 n匹配,那么规范的方法是什么?
在我的情况下,我想解析一个40个字符的Git提交ID - 如果它超过40个字符,那不是一个提交ID,它不应该是匹配.
到目前为止,我在docs中找到的最接近的例子是:
val unicodeEscape = P( "u" ~ hexDigit ~ hexDigit ~ hexDigit ~ hexDigit )
Run Code Online (Sandbox Code Playgroud)
...通过简单的重复匹配4个字符(40个字符的提交ID详细).
这些是解析器组合器,而不是正则表达式,答案就是这样的\p{XDigit}{40}.
Data.Attoparsec.Text出口takeWhile和takeWhile1:
Run Code Online (Sandbox Code Playgroud)takeWhile :: (Char -> Bool) -> Parser Text只要谓词返回
True就消耗输入,并返回消耗的输入.此解析器不会失败.如果谓词
False在输入的第一个字符上返回,它将返回一个空字符串.[...]
Run Code Online (Sandbox Code Playgroud)takeWhile1 :: (Char -> Bool) -> Parser Text只要谓词返回
True就消耗输入,并返回消耗的输入.此解析器要求谓词在至少一个输入字符上成功:如果谓词永不返回
True或者没有输入,则它将失败.
attoparsec的文档鼓励用户
Text尽可能使用面向对象的解析器,例如takeWhile1代替many1 anyChar.两种解析器之间的性能差异大约为100倍.
这两个解析器非常有用,但我一直觉得需要更通用的版本takeWhile1,更具体地说,是一些假设的解析器
takeWhileLo :: (Char -> Bool) -> Int -> Parser Text
takeWhileLo f lo = undefined
Run Code Online (Sandbox Code Playgroud)
这将解析至少 lo满足谓词的字符f,其中lo是任意非负整数.
我看了一下它takeWhile1的实现,但是它使用了一堆私有的函数,Data.Attoparsec.Text.Internal并且似乎不易泛化.
我想出了以下应用实现:
{-# LANGUAGE OverloadedStrings …Run Code Online (Sandbox Code Playgroud) 我一直在尝试使用scala-parser-combinator库构建一个SQL解析器,我已将其大大简化为以下代码。
class Expression
case class FalseExpr() extends Expression
case class TrueExpr() extends Expression
case class AndExpression(expr1: Expression, expr2: Expression) extends Expression
object SimpleSqlParser {
def parse(sql: String): Try[Expression] = new SimpleSqlParser().parse(sql)
}
class SimpleSqlParser extends RegexParsers {
def parse(sql: String): Try[_ <: Expression] = parseAll(expression, sql) match {
case Success(matched,_) => scala.util.Success(matched)
case Failure(msg,remaining) => scala.util.Failure(new Exception("Parser failed: "+msg + "remaining: "+ remaining.source.toString.drop(remaining.offset)))
case Error(msg,_) => scala.util.Failure(new Exception(msg))
}
private def expression: Parser[_ <: Expression] =
andExpr | falseExpr | …Run Code Online (Sandbox Code Playgroud) 我无法弄清楚使用Haskell regex-applicative软件包使用该replace功能对多行注释执行替换的正确方法。首先,我试图match返回正确的字符串作为测试:
regex = pure (++) <$> string "/*" <*> many (anySym) <*> string "*/"
match regex "/* hello world */"
Run Code Online (Sandbox Code Playgroud)
哪个返回hello world */。我不明白为什么第一个匹配部分被切除。有任何想法吗?
我一直在玩Scala解析器组合器已经有一段时间了,并且学习了一些方法来使它表现得很好并且使用内置函数完成我想要的大部分工作.
但是你如何制作嵌入式语言(如php或ruby的erb)?在嵌入真实代码之外,它要求不要忽略空格.
我设法创建一个简单的解析器,匹配所有文本,直到给定的正则表达式匹配,但我正在寻找一个更好,更漂亮的方法来做到这一点.可能有一些已定义的功能可以完成所需的工作.
测试语言解析文本,如:
now: [[ millis; ]]
and now: [[; millis; ]]
Run Code Online (Sandbox Code Playgroud)
并由以下代码生成:
package test
import scala.util.parsing.combinator.RegexParsers
import scala.util.matching.Regex
sealed abstract class Statement
case class Print(s: String) extends Statement
case class Millis() extends Statement
object SimpleLang extends RegexParsers {
def until(r: Regex): Parser[String] = new Parser[String]{
def apply(in: Input) = {
val source = in.source
val offset = in.offset
val start = offset
(r.findFirstMatchIn( source.subSequence(offset, source.length) )) match {
case Some(matched) =>
Success(source.subSequence(offset, offset + matched.start).toString, in.drop(matched.start))
case None …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用解析器组合器解析文本文件.我想捕获一个名为的类中的索引和文本Example.这是一个测试,显示输入文件中的表单:
object Test extends ParsComb with App {
val input = """
0)
blah1
blah2
blah3
1)
blah4
blah5
END
"""
println(parseAll(examples, input))
}
Run Code Online (Sandbox Code Playgroud)
这是我的尝试不起作用:
import scala.util.parsing.combinator.RegexParsers
case class Example(index: Int, text: String)
class ParsComb extends RegexParsers {
def examples: Parser[List[Example]] = rep(divider~example) ^^
{_ map {case d ~ e => Example(d,e)}}
def divider: Parser[Int] = "[0-9]+".r <~ ")" ^^ (_.toInt)
def example: Parser[String] = ".*".r <~ (divider | "END")
}
Run Code Online (Sandbox Code Playgroud)
它失败了:
[4.1] failure: `END' expected but `b' …Run Code Online (Sandbox Code Playgroud) scala ×7
haskell ×3
parsing ×2
regex ×2
applicative ×1
attoparsec ×1
fastparse ×1
lexer ×1
newline ×1