RA parser first draft

This commit is contained in:
Calum Grant
2023-02-22 16:51:16 +00:00
parent dffb12070e
commit 9980756ee8
3 changed files with 168 additions and 0 deletions

View File

@@ -0,0 +1,109 @@
/**
* Parses RA expressions.
*/
signature class RAstring extends string;
signature class RApredicate {
string getLineOfRA(int n);
}
/**
* Parses strings of RA provided by an RA predicate,
*/
module RAParser<RApredicate Predicate> {
private string parseRaExpr(Predicate p, int line, int arity, int lhs) {
exists(string str | str = p.getLineOfRA(line).trim() |
arity = str.regexpCapture("\\{([0-9]+)\\} r([0-9]+) = (.+)", 1).toInt() and
lhs = str.regexpCapture("\\{([0-9]+)\\} r([0-9]+) = (.+)", 2).toInt() and
result = str.regexpCapture("\\{([0-9]+)\\} r([0-9]+) = (.+)", 3)
)
}
bindingset[str]
private int parseReturn(string str) {
result = str.trim().regexpCapture("return r([0-9]+)", 1).toInt()
}
private newtype TRA =
TReturn(Predicate p, int line, int v) { v = parseReturn(p.getLineOfRA(line)) } or
TUnknown(Predicate p, int line, int lhs, int arity, string rhs) {
rhs = parseRaExpr(p, line, arity, lhs)
}
/** An RA Expression. */
abstract class RAExpr extends TRA {
/** Gets the predicate this RA expression belongs to. */
abstract Predicate getPredicate();
/** Gets the line index of this RA expression. */
abstract int getLine();
/** Gets the LHS of the expression of the form `rNN = ...` */
abstract int getLhs();
/** Gets a variable of the form `rNN` in the RHS of the RA expression. */
abstract int getARhsVariable();
/** Gets the given arity of the RA expression. */
abstract int getArity();
/** Gets a predicate name referenced in the RHS of an RA expression. */
abstract string getARhsPredicate();
final string toString() { result = getPredicate().getLineOfRA(getLine()) }
/** Gets a child of this RA expression - not by index yet. */
RAExpr getAChild() {
result.getPredicate() = this.getPredicate() and result.getLhs() = this.getARhsVariable()
}
}
/**
* A generic RA expression - where we haven't precisely parsed the RA expression type.
* For Hackathon purposes, we probably don't need more than this.
*/
class RAUnknownExpr extends RAExpr, TUnknown {
Predicate p;
int line;
string rhs;
int arity;
int lhs;
RAUnknownExpr() { this = TUnknown(p, line, lhs, arity, rhs) }
override int getLine() { result = line }
override Predicate getPredicate() { result = p }
override int getLhs() { result = lhs }
override int getARhsVariable() {
result = rhs.splitAt(" ").regexpCapture("r([0-9]+)", 1).toInt()
}
// This is a dumb regex to find a predicate name - they always contain a `#` (TODO...)
override string getARhsPredicate() { result = rhs.splitAt(" ") and result.indexOf("#") > 0 }
override int getArity() { result = arity }
}
class RAReturnExpr extends RAExpr, TReturn {
RAReturnExpr() { this = TReturn(p, line, res) }
Predicate p;
int line;
int res;
override Predicate getPredicate() { result = p }
override int getLine() { result = line }
override int getLhs() { none() }
override int getARhsVariable() { result = res }
override int getArity() { none() }
override string getARhsPredicate() { none() }
}
}

View File

@@ -0,0 +1,17 @@
children
| return r7 | {4} r7 = r3 UNION r6 |
| {4} r2 = JOIN r1 WITH raparser#d14bb8db::TestPredicate#b ON FIRST 1 OUTPUT "p1", toString("p1"), 123, " r1 = SCAN fubar\\n r1" | {1} r1 = CONSTANT(unique string)["p1"] |
| {4} r3 = STREAM DEDUP r2 | {4} r2 = JOIN r1 WITH raparser#d14bb8db::TestPredicate#b ON FIRST 1 OUTPUT "p1", toString("p1"), 123, " r1 = SCAN fubar\\n r1" |
| {4} r4 = JOIN r1 WITH raparser#d14bb8db::TestPredicate#b ON FIRST 1 OUTPUT "p1", "(no string representation)", 123, " r1 = SCAN fubar\\n r1" | {1} r1 = CONSTANT(unique string)["p1"] |
| {4} r5 = STREAM DEDUP r4 | {4} r4 = JOIN r1 WITH raparser#d14bb8db::TestPredicate#b ON FIRST 1 OUTPUT "p1", "(no string representation)", 123, " r1 = SCAN fubar\\n r1" |
| {4} r6 = r5 AND NOT project##select#query#ffff#nullary({}) | {4} r5 = STREAM DEDUP r4 |
| {4} r7 = r3 UNION r6 | {4} r3 = STREAM DEDUP r2 |
| {4} r7 = r3 UNION r6 | {4} r6 = r5 AND NOT project##select#query#ffff#nullary({}) |
#select
| p1 | 1 | {1} r1 = CONSTANT(unique string)["p1"] | 1 | 1 | 0 | 0 |
| p1 | 3 | {4} r2 = JOIN r1 WITH raparser#d14bb8db::TestPredicate#b ON FIRST 1 OUTPUT "p1", toString("p1"), 123, " r1 = SCAN fubar\\n r1" | 2 | 4 | 1 | 1 |
| p1 | 5 | {4} r3 = STREAM DEDUP r2 | 3 | 4 | 0 | 1 |
| p1 | 6 | {4} r4 = JOIN r1 WITH raparser#d14bb8db::TestPredicate#b ON FIRST 1 OUTPUT "p1", "(no string representation)", 123, " r1 = SCAN fubar\\n r1" | 4 | 4 | 1 | 1 |
| p1 | 7 | {4} r5 = STREAM DEDUP r4 | 5 | 4 | 0 | 1 |
| p1 | 8 | {4} r6 = r5 AND NOT project##select#query#ffff#nullary({}) | 6 | 4 | 1 | 1 |
| p1 | 9 | {4} r7 = r3 UNION r6 | 7 | 4 | 0 | 2 |

View File

@@ -0,0 +1,42 @@
import experimental.RA
class TestPredicate extends string {
TestPredicate() { this = "p1" }
string getLineOfRA(int line) {
line = 1 and
result = " {1} r1 = CONSTANT(unique string)[\"p1\"]"
or
line = 2 and result = ""
or
line = 3 and
result =
" {4} r2 = JOIN r1 WITH raparser#d14bb8db::TestPredicate#b ON FIRST 1 OUTPUT \"p1\", toString(\"p1\"), 123, \" r1 = SCAN fubar\\n r1\""
or
line = 4 and result = ""
or
line = 5 and result = " {4} r3 = STREAM DEDUP r2"
or
line = 6 and
result =
" {4} r4 = JOIN r1 WITH raparser#d14bb8db::TestPredicate#b ON FIRST 1 OUTPUT \"p1\", \"(no string representation)\", 123, \" r1 = SCAN fubar\\n r1\""
or
line = 7 and result = " {4} r5 = STREAM DEDUP r4"
or
line = 8 and result = " {4} r6 = r5 AND NOT project##select#query#ffff#nullary({})"
or
line = 9 and result = " {4} r7 = r3 UNION r6"
or
line = 10 and result = " return r7"
}
}
query predicate children(
RAParser<TestPredicate>::RAExpr parent, RAParser<TestPredicate>::RAExpr child
) {
child = parent.getAChild()
}
from RAParser<TestPredicate>::RAExpr expr
select expr.getPredicate(), expr.getLine(), expr, expr.getLhs(), expr.getArity(),
count(expr.getARhsPredicate()), count(expr.getARhsVariable())