import zio.test._
import zio.test.Assertion._
import org.parboiled2.ParseError
object ParserTests {
val str0 =
"""node Regbuffer :
module Shit :""".stripMargin
val stringSuite = suite("Simple string suite")(
test("Node Module parsing") {
val par = new MyParser(str0)
val res = par.start.run()
val out = res.fold(ex => par.formatError(ex.asInstanceOf[ParseError]), v => v)
assert(out, equalTo(Vector(NodeAST("Regbuffer"), ModuleAST("Shit"))))
})
tag key0 : value0, key1 : value1
. However, the output AST Node depends on whether or not I had a tag
for that key. Here's my impl:def flip: Rule1[Boolean] = rule {
capture(Word) ~ ws ~> (
(s: String) => test(s == "tag0") ~ push(true)
)
}
def record: Rule1[BusAST] = rule {
flip ~ capture(Word) ~ Col ~ bus ~ ws ~> (
(
check: Boolean,
name: String,
tpe: String,
len: Int
) => BusAST(if (check) Out else In, name, tpe, len)
)
}
key1 : value1
. I also tried this:def record: Rule1[BusAST] = rule {
optional(atomic("tag0")) ~ ws ~ capture(Word) ~ Col ~ bus ~ ws ~> (
(
_,
name: String,
tpe: String,
len: Int
) => BusAST(if (true) Out else In, name, tpe, len)
)
}
def record: Rule1[BusAST] = rule {
optional(atomic(capture("tag0”))) ~ ws ~ capture(Word) ~ Col ~ bus ~ ws ~> (
(
tagOpt: Option[String],
name: String,
tpe: String,
len: Int
) => BusAST(if (tagOpt.isDefined) Out else In, name, tpe, len)
)
}
(test("tag0") ~ push(Out) | push(In))
passes the typer and derives the correct least supertype of In
and Out
. you should check on your side
test(true)
to make this compile, since test requires Boolean
on input, not String
{
found : org.parboiled2.Rule[shapeless.HNil,Product with Serializable :: shapeless.HNil]
required: org.parboiled2.Rule[shapeless.HNil,chipa.parser.ast.BusAST :: shapeless.HNil]"
}
Any ideas how to fix ?|
and ~
operators. ~
has higher one. that means that you’re making two alternatives:test(true) ~ push(Out)
and push(In) ~ ws ~ capture(Word) ~ Col ~ bus ~ ws ~> BusAST
. and apparently the least common supertype of Out
and BusAST
is Product with Serializable
hi @Tieru
take a look at that project parser https://github.com/sangria-graphql/sangria/blob/master/src/main/scala/sangria/parser/QueryParser.scala
So I have this:
def term: Rule0 = rule { termMatch1 | termMatch2 }
private def termMatch1: Rule0 = rule { '@' ~ oneOrMore(All) }
private def termMatch2: Rule0 = rule { oneOrMore(AlphaNum) }
But I have to exclude terms that match
private def termExclude: Rule0 = rule { '@' ~ oneOrMore(AlphaNum) }
def Node: Rule[String :: String :: HNil, NodeAST :: HNil]
, which compiles fine. However, when I try to add it to the root rule
, I'm getting an error message: The
optional,
zeroOrMore,
oneOrMoreand
timesmodifiers can only be used on rules of type
Rule0,
Rule1[T]and
Rule[I, O <: I]!
oneOfMore(Node)
Hello ! I'm thinking about the best approach to attack the following parsing problem. Suppose I have the following input grammar:
when _T :
tmp <= UInt<1>("h00")
skip
else :
node _T_1 = add(tmp, UInt<1>("h01"))
node _T_2 = tail(_T_1, 1)
skip
That's essentially a logic block, which spans multiple lines. It starts with a when
statement and has two branches : when
and else
. As far as the number of lines in each branch is variable (zero to many) and right-hand-side deps may be implemented aside the when
block, I can not put this statement into a fixed case class
like
final case class MyWhen( cond:String, node0: Node, node1:Node)
How would you parse this input? Any advice and example is appreciated . Thank you!
@tampler
Is there any way to selectively parse the input? Say, I'd love to have a single pass, which parses only lines, which start with input or output like this:
I suggest you to extract those lines with RegEx. and then apply a parser
Hi all,
When defining a grammar in Parboiled 1, is there an option to specify that a specific term/token should only appear {n,m} times?
Also is it possible to create a Parboiled parser for a data format language like this:
SIZE CHAR{SIZE}
where CHAR appears SIZE
times AND SIZE
is a two digit zero padded number, e.g:
05HELLO
11PROGRAMMING
Hi, I used Parboiled1 (Java) in the past and I'm currently evaluating Parboiled2 due to its performance promises :-) I'm wondering how to provide proper location information (startOffset, endOffset) to the AST nodes pushed to the value stack.
In Parboiled1 I had two Actions within a rule; first ACTION to push the node with the current offset (startOffset) to the value stack and second ACTION to set the endOffset to this node:
Sequence(
ACTION(factory.createNode()),
matchingRules(),
ACTION(factory.finalizeNode())
)
How should this be implemented in Parboiled2?