-
Notifications
You must be signed in to change notification settings - Fork 1
Added parser for While. #12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 3 commits
015aa4b
f9bb69b
fda210c
c94648d
073dc1a
c0c91a9
e38efcf
50adcbc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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) |
| 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) ) } | ||
|
|
||
| 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) }) | ||
| } | ||
| 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))) | ||
| } | ||
| } |
| 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)) | ||
| } | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. А тесты по-больше?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Это маленький примерчик, увидела в книжке -- добавила, он не особо показателен. Распознаем шпильки (hairpin) с длиной спирали 3 и последовательностью в петле gaaa и gcaa. В языке, порождаемым этой грамматикой, строки всегда одной длины (10 символов). |
||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
} на новую строчку