WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

Commit c6359c4

Browse files
committed
Add IRBuilder for Repeat
1 parent 205ba52 commit c6359c4

File tree

4 files changed

+90
-14
lines changed

4 files changed

+90
-14
lines changed

modules/resyntax/shared/src/main/scala/codes/quine/labs/resyntax/ir/IRBuilder.scala

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import codes.quine.labs.resyntax.ast.FlagSetDiff
77
import codes.quine.labs.resyntax.ast.GroupKind
88
import codes.quine.labs.resyntax.ast.Node
99
import codes.quine.labs.resyntax.ast.NodeData
10+
import codes.quine.labs.resyntax.ast.Quantifier
1011
import codes.quine.labs.resyntax.ir.IRBuilder.BuildingContext
1112

1213
/** IRBuilder is a builder from AST node to IR. */
@@ -23,7 +24,7 @@ object IRBuilder {
2324
}
2425

2526
object BuildingContext {
26-
def from(flagSet: FlagSet, featureSet: IRFeatureSet): BuildingContext =
27+
def from(flagSet: FlagSet): BuildingContext =
2728
BuildingContext(
2829
multiline = flagSet.multiline
2930
)
@@ -43,25 +44,25 @@ private[ir] class IRBuilder(
4344
private[this] val dialect: Dialect,
4445
private[this] val featureSet: IRFeatureSet
4546
) {
46-
var context: BuildingContext = BuildingContext.from(flagSet, featureSet)
47+
var context: BuildingContext = BuildingContext.from(flagSet)
4748

4849
var nextIndex: Int = 1
4950

5051
def build(): IRNode = build(node)
5152

5253
def build(node: Node): IRNode = {
5354
val result = node.data match {
54-
case NodeData.Disjunction(children) => buildDisjunction(children)
55-
case NodeData.Sequence(children) => buildSequence(children)
56-
case NodeData.Repeat(_, _) => ???
57-
case NodeData.Group(kind, child) => buildGroup(node, kind, child)
58-
case NodeData.Command(kind) => buildCommand(node, kind)
59-
case NodeData.Caret => Left(buildCaret())
60-
case NodeData.Dollar => Left(buildDollar())
61-
case NodeData.Dot => ???
62-
case NodeData.Backslash(_) => ???
63-
case NodeData.Class(_, _) => ???
64-
case NodeData.Literal(_) => ???
55+
case NodeData.Disjunction(children) => buildDisjunction(children)
56+
case NodeData.Sequence(children) => buildSequence(children)
57+
case NodeData.Repeat(child, quantifier) => Left(buildRepeat(child, quantifier))
58+
case NodeData.Group(kind, child) => buildGroup(node, kind, child)
59+
case NodeData.Command(kind) => buildCommand(node, kind)
60+
case NodeData.Caret => Left(buildCaret())
61+
case NodeData.Dollar => Left(buildDollar())
62+
case NodeData.Dot => ???
63+
case NodeData.Backslash(_) => ???
64+
case NodeData.Class(_, _) => ???
65+
case NodeData.Literal(_) => ???
6566
}
6667
result match {
6768
case Left(data) => IRNode(data, node.loc)
@@ -78,6 +79,21 @@ private[ir] class IRBuilder(
7879
case children => Left(IRNodeData.Sequence(children.map(build)))
7980
}
8081

82+
def buildRepeat(child: Node, quantifier: Quantifier): IRNodeData = {
83+
val q = quantifier match {
84+
case Quantifier.Star(strategy) => IRQuantifier.Unbounded(0, strategy)
85+
case Quantifier.Plus(strategy) => IRQuantifier.Unbounded(1, strategy)
86+
case Quantifier.Question(strategy) => IRQuantifier.Bounded(0, 1, strategy)
87+
case Quantifier.Exact(n, _) => IRQuantifier.Exact(n)
88+
case Quantifier.Bounded(min, max, _) if min == max => IRQuantifier.Exact(min)
89+
case Quantifier.Bounded(min, max, strategy) => IRQuantifier.Bounded(min, max, strategy)
90+
case Quantifier.MaxBounded(0, _) => IRQuantifier.Exact(0)
91+
case Quantifier.MaxBounded(max, strategy) => IRQuantifier.Bounded(0, max, strategy)
92+
case Quantifier.Unbounded(min, strategy) => IRQuantifier.Unbounded(min, strategy)
93+
}
94+
IRNodeData.Repeat(build(child), q)
95+
}
96+
8197
def buildCommand(node: Node, kind: CommandKind): Either[IRNodeData, IRNode] = kind match {
8298
case CommandKind.InlineFlag(_) => ???
8399
case CommandKind.ResetFlag(_) => ???

modules/resyntax/shared/src/main/scala/codes/quine/labs/resyntax/ir/IRNodeData.scala

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ sealed abstract class IRNodeData extends Product with Serializable {
99
ls.length == rs.length && ls.zip(rs).forall { case (l, r) => l.equalsWithoutLoc(r) }
1010
case (IRNodeData.Sequence(ls), IRNodeData.Sequence(rs)) =>
1111
ls.length == rs.length && ls.zip(rs).forall { case (l, r) => l.equalsWithoutLoc(r) }
12+
case (IRNodeData.Repeat(l, lq), IRNodeData.Repeat(r, rq)) =>
13+
lq == rq && l.equalsWithoutLoc(r)
1214
case (IRNodeData.Capture(li, ln, l), IRNodeData.Capture(ri, rn, r)) =>
1315
li == ri && ln == rn && l.equalsWithoutLoc(r)
1416
case (IRNodeData.Unsupported(l), IRNodeData.Unsupported(r)) => l.equalsWithoutLoc(r)
@@ -29,14 +31,22 @@ object IRNodeData {
2931
Sequence(nodes.map(IRNode(_)))
3032
}
3133

32-
/** Disjunction is a disjuncyion of nodes. */
34+
/** Disjunction is a disjunction of nodes. */
3335
final case class Disjunction(nodes: Seq[IRNode]) extends IRNodeData
3436

3537
object Disjunction {
3638
def apply(nodes: IRNodeData*): IRNodeData =
3739
Disjunction(nodes.map(IRNode(_)))
3840
}
3941

42+
/** Repeat is a repetition node. */
43+
final case class Repeat(node: IRNode, quantifier: IRQuantifier) extends IRNodeData
44+
45+
object Repeat {
46+
def apply(node: IRNodeData, quantifier: IRQuantifier): IRNodeData =
47+
Repeat(IRNode(node), quantifier)
48+
}
49+
4050
/** Assert is a simple zero-width assertion. */
4151
final case class Assert(kind: IRAssertKind) extends IRNodeData
4252

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package codes.quine.labs.resyntax.ir
2+
3+
import codes.quine.labs.resyntax.ast.BacktrackStrategy
4+
5+
sealed abstract class IRQuantifier extends Product with Serializable
6+
7+
object IRQuantifier {
8+
9+
/** Exact is a exact number bounded quantifier. */
10+
final case class Exact(n: Int) extends IRQuantifier
11+
12+
/** Bounded is a bounded quantifier. */
13+
final case class Bounded(min: Int, max: Int, strategy: BacktrackStrategy) extends IRQuantifier
14+
15+
/** Unbounded is a unbounded quantifier. */
16+
final case class Unbounded(min: Int, strategy: BacktrackStrategy) extends IRQuantifier
17+
}

modules/resyntax/shared/src/test/scala/codes/quine/labs/resyntax/ir/IRBuilderSuite.scala

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package codes.quine.labs.resyntax.ir
22

33
import codes.quine.labs.resyntax.ast.AssertNameStyle
44
import codes.quine.labs.resyntax.ast.BacktrackControlKind
5+
import codes.quine.labs.resyntax.ast.BacktrackStrategy._
56
import codes.quine.labs.resyntax.ast.CommandKind
67
import codes.quine.labs.resyntax.ast.ConditionalTest
78
import codes.quine.labs.resyntax.ast.Dialect
@@ -12,6 +13,7 @@ import codes.quine.labs.resyntax.ast.NameStyle
1213
import codes.quine.labs.resyntax.ast.Node
1314
import codes.quine.labs.resyntax.ast.NodeData
1415
import codes.quine.labs.resyntax.ir.IRNodeData._
16+
import codes.quine.labs.resyntax.ir.IRQuantifier._
1517
import codes.quine.labs.resyntax.parser.Parser
1618

1719
class IRBuilderSuite extends munit.FunSuite {
@@ -35,6 +37,37 @@ class IRBuilderSuite extends munit.FunSuite {
3537
check("", "", All: _*)(Empty)
3638
check("(?:)(?:)", "", All: _*)(Sequence(Empty, Empty))
3739

40+
// Repeat
41+
check("(?:)*", "", All: _*)(Repeat(Empty, Unbounded(0, Greedy)))
42+
check("(?:)*?", "", All: _*)(Repeat(Empty, Unbounded(0, Lazy)))
43+
check("(?:)*+", "", Java, PCRE, Perl, Ruby)(Repeat(Empty, Unbounded(0, Possessive)))
44+
check("(?:)+", "", All: _*)(Repeat(Empty, Unbounded(1, Greedy)))
45+
check("(?:)+?", "", All: _*)(Repeat(Empty, Unbounded(1, Lazy)))
46+
check("(?:)++", "", Java, PCRE, Perl, Ruby)(Repeat(Empty, Unbounded(1, Possessive)))
47+
check("(?:)?", "", All: _*)(Repeat(Empty, Bounded(0, 1, Greedy)))
48+
check("(?:)??", "", All: _*)(Repeat(Empty, Bounded(0, 1, Lazy)))
49+
check("(?:)?+", "", Java, PCRE, Perl, Ruby)(Repeat(Empty, Bounded(0, 1, Possessive)))
50+
check("(?:){4}", "", All: _*)(Repeat(Empty, Exact(4)))
51+
check("(?:){4}?", "", DotNet, Java, JavaScript, PCRE, Perl, Python)(Repeat(Empty, Exact(4)))
52+
check("(?:){4}?", "", Ruby)(Repeat(Repeat(Empty, Exact(4)), Bounded(0, 1, Greedy)))
53+
check("(?:){4}+", "", Java, PCRE, Perl)(Repeat(Empty, Exact(4)))
54+
check("(?:){4}+", "", Ruby)(Repeat(Repeat(Empty, Exact(4)), Unbounded(1, Greedy)))
55+
check("(?:){2,3}", "", All: _*)(Repeat(Empty, Bounded(2, 3, Greedy)))
56+
check("(?:){2,2}", "", All: _*)(Repeat(Empty, Exact(2)))
57+
check("(?:){2,3}?", "", All: _*)(Repeat(Empty, Bounded(2, 3, Lazy)))
58+
check("(?:){2,2}?", "", All: _*)(Repeat(Empty, Exact(2)))
59+
check("(?:){2,3}+", "", Java, PCRE, Perl, Ruby)(Repeat(Empty, Bounded(2, 3, Possessive)))
60+
check("(?:){2,2}+", "", Java, PCRE, Perl, Ruby)(Repeat(Empty, Exact(2)))
61+
check("(?:){,1}", "", Perl, Python, Ruby)(Repeat(Empty, Bounded(0, 1, Greedy)))
62+
check("(?:){,0}", "", Perl, Python, Ruby)(Repeat(Empty, Exact(0)))
63+
check("(?:){,1}?", "", Perl, Python, Ruby)(Repeat(Empty, Bounded(0, 1, Lazy)))
64+
check("(?:){,0}?", "", Perl, Python, Ruby)(Repeat(Empty, Exact(0)))
65+
check("(?:){,1}+", "", Perl, Ruby)(Repeat(Empty, Bounded(0, 1, Possessive)))
66+
check("(?:){,0}+", "", Perl, Ruby)(Repeat(Empty, Exact(0)))
67+
check("(?:){2,}", "", All: _*)(Repeat(Empty, Unbounded(2, Greedy)))
68+
check("(?:){2,}?", "", All: _*)(Repeat(Empty, Unbounded(2, Lazy)))
69+
check("(?:){2,}+", "", Java, PCRE, Perl, Ruby)(Repeat(Empty, Unbounded(2, Possessive)))
70+
3871
// Command
3972
check("(?R)", "", PCRE, Perl)(Unsupported(NodeData.Command(CommandKind.RCall)))
4073
check("(?1)", "", PCRE, Perl)(Unsupported(NodeData.Command(CommandKind.IndexedCall(1))))

0 commit comments

Comments
 (0)