Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/main/net/podkopaev/cpsComb.kt
Original file line number Diff line number Diff line change
Expand Up @@ -357,12 +357,12 @@ val alpha: Recognizer<Char> = satp {
val alphaOrDigit: Recognizer<Char> = alpha / digit
val number: Recognizer<Int> = (digit map {it-> it.toString().toInt()}) / (many1(digit) map { it.toStr().toInt() })
val word : Recognizer<String> = many1(alpha) map { it.toStr() }
val symbol: Recognizer<String> = seq(alpha, many0(alphaOrDigit)) map {
val symbol: Recognizer<String> = (seq(alpha, many0(alphaOrDigit)) map {
val sb = StringBuilder()
sb.append(it.first)
it.second.forEach { sb.append(it) }
sb.toString()
}
}) / (alpha map { t -> t.toString() })
fun <A> leftAssocp(opp: Recognizer<String>, elemp: Recognizer<A>,
f: (String, A, A) -> A): Recognizer<A> {
val rightp = opp + elemp
Expand Down
30 changes: 30 additions & 0 deletions src/main/net/podkopaev/grammar/HairpinGrammar.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package net.podkopaev.grammar.HairpinGrammar

import net.podkopaev.cpsComb.*
/**
* A context-free grammar for an RNA stem loop.
* S -> aW1u | cW1g | gW1c | uW1a
* W1 -> aW2u | cW2g | gW2c | uW2a
* W2 -> aW3u | cW3g | gW3c | uW3a
* W3 -> gaaa | gcaa
*
*/

val a = terminal("a") map { 1 }
val u = terminal("u") map { 1 }
val c = terminal("c") map { 1 }
val g = terminal("g") map { 1 }

val pl = { t:Pair<Pair<Int, Int>, Int> -> t.first.second + 2 }

val pW3: Recognizer<Int> = (seq(seq(seq(g, a), a), a) map { t -> t.first.first.second + 3 }) /
(seq(seq(seq(g, c), a), a) map { t -> t.first.first.second + 3 })

val pW2: Recognizer<Int> = (seq(seq(a, pW3), u) map pl) / (seq(seq(c, pW3), g) map pl) /
(seq(seq(g, pW3), c) map pl) / (seq(seq(u, pW3), a) map pl)

val pW1: Recognizer<Int> = (seq(seq(a, pW2), u) map pl) / (seq(seq(c, pW2), g) map pl) /
(seq(seq(g, pW2), c) map pl) / (seq(seq(u, pW2), a) map pl)

val pS: Recognizer<Int> = (seq(seq(a, pW1), u) map pl) / (seq(seq(c, pW1), g) map pl) /
(seq(seq(g, pW1), c) map pl) / (seq(seq(u, pW1), a) map pl)
63 changes: 63 additions & 0 deletions src/main/net/podkopaev/whileParser/cpsParser.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package net.podkopaev.cpsParser

import net.podkopaev.cpsComb.*
import net.podkopaev.whileParser.Expr
import net.podkopaev.whileParser.Stmt

val corep: Recognizer<Expr> = fix { (number map { Expr.Con(it) as Expr }) /
(symbol map { Expr.Var(it) as Expr }) /
paren( sp(it) ) }
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

} на новую строчку


val op1p: Recognizer<Expr> = fix { rightAssocp(sp(terminal("^")), corep) { l, op, r -> Expr.Binop(l, op, r) }}

val op2p: Recognizer<Expr> = fix {
rightAssocp(sp(terminal("*") / terminal("/") / terminal("%")), op1p) {
op, e1, e2 ->
Expr.Binop(op, e1, e2)
}
}

val op3p: Recognizer<Expr> = fix {
leftAssocp(sp(terminal("+") / terminal("-")), op2p) {
op, e1, e2 ->
Expr.Binop(op, e1, e2)
}
}

val exprParser: Recognizer<Expr> = fix { corep / op1p / op3p / op2p }

val readp: Recognizer<Stmt> = fix { terminal("read" ) seqr spaces seqr paren(sp(symbol)) map { Stmt.Read (it) as Stmt } }
val writep: Recognizer<Stmt> = fix { terminal("write") seqr spaces seqr paren(sp(exprParser)) map { Stmt.Write(it) as Stmt } }
val assignp: Recognizer<Stmt> = fix {
((symbol seql spaces seql terminal(":=") seql spaces) + exprParser) map { nameexpr ->
Stmt.Assign(nameexpr.first, nameexpr.second) as Stmt
}
}

val ifp:Recognizer<Stmt> = fix {
(terminal("if") seqr spaces seqr exprParser seql spaces) +
(terminal("then") seqr spaces seqr it seql spaces) +
(terminal("else") seqr spaces seqr it seql spaces) - terminal("fi") map
{ ete ->
Stmt.If(ete.first.first, ete.first.second, ete.second) as Stmt
}
}
val whilep: Recognizer<Stmt> = fix {
(terminal("while") seqr spaces seqr sp(exprParser) seql spaces) +
(terminal("do") seqr spaces seqr sp(it) seql spaces) -
terminal("od") map {
eb ->
Stmt.While(eb.first, eb.second) as Stmt
}
}

val corepp: Recognizer<Stmt> = writep / assignp / readp

val stmtParser: Recognizer<Stmt> =
rightAssocpp(terminal(";"), corepp) {
op, s1, s2 -> Stmt.Seq(s1, s2)
}
fun <A> rightAssocpp(opp: Recognizer<String>, elemp: Recognizer<A>,
f: (String, A, A) -> A): Recognizer<A> = fix { P ->
elemp / ((elemp + opp + P) map { f(it.first.second, it.first.first, it.second) })
}
94 changes: 94 additions & 0 deletions src/test/net/podkopaev/LCpsParserTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package net.podkopaev.whileParser.cpsParser

import net.podkopaev.cpsParser.*
import net.podkopaev.whileParser.Expr


import org.junit.Assert
import org.junit.Test

class LCpsParserTest {
@Test fun test0() {
val parser = exprParser
Assert.assertEquals(Expr.Con(123), parser.parse("123", parser))
}

@Test fun test01() {
val parser = exprParser
Assert.assertEquals(Expr.Con(123), parser.parse("( 123 )", parser))
}
@Test fun test1() {
val parser = exprParser
val result = parser.parse("abc0", parser)
Assert.assertEquals(Expr.Var("abc0"), result)
}
@Test fun test2() {
val parser = exprParser
val result = parser.parse("1 ^ 2 ^ 3", parser)
Assert.assertEquals(Expr.Binop("^", Expr.Con(1),
Expr.Binop("^", Expr.Con(2), Expr.Con(3))),
result)
}
@Test fun test03() {
val parser = exprParser
val result = parser.parse("1 + 2", parser)
Assert.assertEquals(Expr.Binop("+", Expr.Con(1), Expr.Con(2)),
result)
}

@Test fun test4() {
val parser = exprParser
val result = parser.parse("1 + 2 + 3", parser)
Assert.assertEquals(Expr.Binop("+", Expr.Binop("+", Expr.Con(1), Expr.Con(2)),
Expr.Con(3)),
result)
}

@Test fun test5() {
val parser = exprParser
val result = parser.parse("1 + 2 * 3", parser)
Assert.assertEquals(7, result?.calc(hashMapOf()))
}

@Test fun test7() {
val parser = stmtParser
val result = parser.parse("write ( 5 )", parser)
Assert.assertEquals(listOf(5), result?.interpret(listOf()))
}

@Test fun test8() {
val parser = stmtParser
val result = parser.parse("x0 := 8 - 2;write ( x0 )", parser)
Assert.assertEquals(listOf(6), result?.interpret(listOf()))
}

@Test fun test9() {
val parser = stmtParser
val result = parser.parse("write ( 5 + 8 );write ( 5 )", parser)
Assert.assertEquals(listOf(13,5), result?.interpret(listOf()))
}

@Test fun test10() {
val parser = stmtParser
val result = parser.parse("x := 3;write ( 5 );write ( 10 )", parser)
Assert.assertEquals(listOf(5, 10), result?.interpret(listOf()))
}

@Test fun test11() {
val parser = stmtParser
val result = parser.parse("x := 3", parser)
Assert.assertEquals(listOf<Int>(), result?.interpret(listOf()))
}
@Test fun test12() {
val program = "read ( n )"
val parser = readp
val result = parser.parse(program, parser)
Assert.assertEquals(listOf<Int>(), result?.interpret(listOf(2)))
}
@Test fun test13() {
val program = "read ( n );read ( k )"
val parser = stmtParser
val result = parser.parse(program, parser)
Assert.assertEquals(listOf<Int>(), result?.interpret(listOf(2, 5)))
}
}
32 changes: 32 additions & 0 deletions src/test/net/podkopaev/grammar/HairpinGrammarTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package net.podkopaev.grammar.HairpinGrammar

import org.junit.Assert
import org.junit.Test

class HairpinGrammarTest {
@Test fun test1() {
val p = pS
val inp = "aaagaaauuu"
Assert.assertEquals(inp.length, p.parse(inp, p))
}
@Test fun test2() {
val p = pS
val inp = "cacgaaagug"
Assert.assertEquals(inp.length, p.parse(inp, p))
}
@Test fun test3() {
val p = pS
val inp = "guagcaauac"
Assert.assertEquals(inp.length, p.parse(inp, p))
}
@Test fun test4() {
val p = pS
val inp = "uuugcaaaaa"
Assert.assertEquals(inp.length, p.parse(inp, p))
}
@Test fun test5() {
val p = pS
val inp = "aucgaaagau"
Assert.assertEquals(inp.length, p.parse(inp, p))
}
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А тесты по-больше?

Copy link
Copy Markdown
Collaborator Author

@onewhl onewhl May 19, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Это маленький примерчик, увидела в книжке -- добавила, он не особо показателен. Распознаем шпильки (hairpin) с длиной спирали 3 и последовательностью в петле gaaa и gcaa. В языке, порождаемым этой грамматикой, строки всегда одной длины (10 символов).

}