Skip to content

Commit

Permalink
Modify ts in compiler and add tsc compile.
Browse files Browse the repository at this point in the history
  • Loading branch information
SoraSuegami committed Nov 2, 2023
1 parent 1aed620 commit 818eb95
Show file tree
Hide file tree
Showing 8 changed files with 164 additions and 48 deletions.
2 changes: 1 addition & 1 deletion packages/compiler/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "zk-regex-compiler"
version = "1.0.5"
version = "1.0.6"
authors = [
"Javier Su <[email protected]>",
"Kata Choi <[email protected]>",
Expand Down
11 changes: 6 additions & 5 deletions packages/compiler/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@zk-email/zk-regex-compiler",
"version": "1.0.5",
"version": "1.0.6",
"description": "a compiler to generate a regex verification circuit in circom from a user-defined regex. Please check [zk-regex](https://github.com/zkemail/zk-regex/tree/main) for the detail.",
"main": "index.node",
"contributors": [
Expand All @@ -14,19 +14,20 @@
"url": "git+https://github.com/zkemail/zk-regex.git"
},
"scripts": {
"build": "cargo-cp-artifact -nc index.node -- cargo build --message-format=json-render-diagnostics",
"build": "npx tsc && cargo-cp-artifact -nc index.node -- cargo build --message-format=json-render-diagnostics",
"build-debug": "npm run build --",
"build-release": "npm run build -- --release",
"install": "node-pre-gyp install --fallback-to-build=false || npm run build-release",
"install": "npx tsc && node-pre-gyp install --fallback-to-build=false || npm run build-release",
"test": "cargo test",
"package": "node-pre-gyp package",
"upload-binary": "npm run package && node-pre-gyp-github publish"
},
"license": "MIT",
"dependencies": {
"cargo-cp-artifact": "^0.1",
"@mapbox/node-pre-gyp": "^1.0",
"node-pre-gyp-github": "https://github.com/ultamatt/node-pre-gyp-github.git"
"cargo-cp-artifact": "^0.1",
"node-pre-gyp-github": "https://github.com/ultamatt/node-pre-gyp-github.git",
"typescript": "^5.2.2"
},
"binary": {
"module_name": "index",
Expand Down
4 changes: 4 additions & 0 deletions packages/compiler/src/circom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ impl RegexAndDFA {
let circom = gen_circom_allstr(&self.dfa_val, template_name)?;
if gen_substrs {
self.add_substrs_constraints(circom_path, circom)?;
} else {
let mut circom_file = File::create(circom_path)?;
write!(circom_file, "{}", circom)?;
circom_file.flush()?;
}
Ok(())
}
Expand Down
24 changes: 13 additions & 11 deletions packages/compiler/src/gen_circom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ function genCircomAllstr(graph_json: Graph, template_name: string): string {
to_init_graph.push([]);
}

let accept_nodes: Set<number> = new Set();
const accept_nodes: Set<number> = new Set();
for (let i = 0; i < N; i++) {
const node = graph_json[i];
for (let k in node.edges) {
Expand All @@ -43,21 +43,22 @@ function genCircomAllstr(graph_json: Graph, template_name: string): string {

if (init_going_state !== null) {
for (const [going_state, chars] of Object.entries(to_init_graph)) {
const going_state_num = Number(going_state);
if (chars.length === 0) {
continue;
}
if (rev_graph[going_state][init_going_state] == null) {
rev_graph[going_state][init_going_state] = [];
if (rev_graph[going_state_num][init_going_state] == null) {
rev_graph[going_state_num][init_going_state] = [];
}
rev_graph[going_state][init_going_state] = rev_graph[going_state][init_going_state].concat(chars);
rev_graph[going_state_num][init_going_state] = rev_graph[going_state_num][init_going_state].concat(chars);
}
}

if (accept_nodes[0] === null) {
throw new Error("accept node must not be 0");
if (accept_nodes.size === 0) {
throw new Error("accept node must exist");
}
accept_nodes.add([...accept_nodes][0]);
if (accept_nodes.size !== 1) {
const accept_nodes_array = [...accept_nodes];
if (accept_nodes_array.length !== 1) {
throw new Error("the size of accept nodes must be one");
}

Expand All @@ -80,8 +81,9 @@ function genCircomAllstr(graph_json: Graph, template_name: string): string {
for (let i = 1; i < N; i++) {
const outputs: number[] = [];
// let is_negates = [];
for (let prev_i of Object.keys(rev_graph[i])) {
const k = rev_graph[i][prev_i];
for (const prev_i of Object.keys(rev_graph[i])) {
const prev_i_num = Number(prev_i);
const k = rev_graph[i][prev_i_num];
k.sort((a, b) => Number(a) - Number(b));
const eq_outputs: [string, number][] = [];
let vals: Set<number> = new Set(k);
Expand Down Expand Up @@ -270,7 +272,7 @@ function genCircomAllstr(graph_json: Graph, template_name: string): string {

lines = declarations.concat(init_code).concat(lines);

const accept_node: number = accept_nodes[0];
const accept_node: number = accept_nodes_array[0];
const accept_lines = [""];
accept_lines.push("\tcomponent final_state_result = MultiOR(num_bytes+1);");
accept_lines.push("\tfor (var i = 0; i <= num_bytes; i++) {");
Expand Down
1 change: 1 addition & 0 deletions packages/compiler/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ impl DecomposedRegexConfig {
all_regex += &config.regex_def;
}
let dfa_val = regex_to_dfa(&all_regex)?;
println!("dfa_val {:?}", dfa_val);
let substrs_defs = self.extract_substr_ids(&dfa_val)?;
Ok(RegexAndDFA {
// max_byte_size: self.max_byte_size,
Expand Down
61 changes: 31 additions & 30 deletions packages/compiler/src/regex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ type CusNode = {
type?: string;
sub?: CusNode;
parts?: CusNode[];
text?: string;
text?: string | [string];
begin: number;
end: number;
}

type NfaEdge = [string, NfaNode];
type NfaEdge = [string | [string], NfaNode];

type NfaNode = {
type: string;
Expand All @@ -33,10 +33,11 @@ type DfaNode = {
id: string | number;
key: string,
items: NfaNode[],
symbols: string[],
symbols: (string | [string])[],
type: string,
edges: DfaEdge[],
trans: Record<string, DfaNode>;
trans: { [key: string | [string]]: DfaNode },
// trans: Record<string | [string], DfaNode>;
nature: number;
};

Expand All @@ -61,7 +62,7 @@ type DfaNode = {
*/
function parseRegex(text: string): CusNode | string {
'use strict';
function parseSub(text: string, begin: number, end: number, first: boolean): CusNode | string {
function parseSub(text: (string | [string])[], begin: number, end: number, first: boolean): CusNode | string {
var i: number,
sub: CusNode | string,
last: number = 0,
Expand Down Expand Up @@ -205,16 +206,16 @@ function parseRegex(text: string): CusNode | string {
return node;
}

let char: string = '';
let new_text: string = '';
let char: string | [string];
let new_text: (string | [string])[] = [];
let i: number = 0;
let is_in_brancket: boolean = false;
let brancket_text: string = '';
let brancket_text: (string | [string])[] = [];
while (i < text.length) {
char = text[i];

if (text[i] == '\\') {
char = text[i + 1];
char = [text[i + 1]];
// new_text.push([text[i + 1]]);
i += 1;
}
Expand All @@ -224,7 +225,7 @@ function parseRegex(text: string): CusNode | string {
return `Error: unexpected [ at ${i}.`;
}
is_in_brancket = true;
brancket_text = '';
brancket_text = [];
// new_text.push(char);
i += 1;
} else if (char === ']') {
Expand All @@ -234,11 +235,10 @@ function parseRegex(text: string): CusNode | string {
is_in_brancket = false;

if (brancket_text[0] === '^') {
brancket_text = brancket_text.slice(1);
let rev_text: string = '';
let code_char: string = '';
const brancket_text_array: string[] = brancket_text.split('');
const brancket_text_jsons: string[] = brancket_text_array.map((c) => JSON.stringify(c));
brancket_text.shift();
let rev_text: (string | [string])[] = [];
let code_char: string | [string] = '';
const brancket_text_jsons = brancket_text.map(val => JSON.stringify(val));
for (let idx = 0; idx < 255; idx++) {
code_char = String.fromCodePoint(idx);

Expand All @@ -257,26 +257,26 @@ function parseRegex(text: string): CusNode | string {
'|',
'-'
].indexOf(code_char) != -1) {
code_char = code_char[0];
code_char = [code_char];
}

if (brancket_text_jsons.indexOf(JSON.stringify(code_char)) === -1) {
rev_text += code_char;
rev_text.push(code_char);
}
}

brancket_text = rev_text;
}

new_text += '(';
new_text.push('(');

for (const c of brancket_text) {
new_text += c;
new_text += '|';
new_text.push(c);
new_text.push('|');
}

new_text = new_text.slice(0, -1);
new_text += ')';
new_text.push(')');
i += 1;
} else if (is_in_brancket) {
if (!Array.isArray(char) && ['(', ')', '[', '*', '+', '?', 'ϵ'].includes(char)) {
Expand All @@ -288,10 +288,10 @@ function parseRegex(text: string): CusNode | string {
}
// new_text.push(char);
// new_text.push('|');
brancket_text += char;
brancket_text.push(char);
i += 1;
} else {
new_text += char;
new_text.push(char);
i += 1;
}
}
Expand Down Expand Up @@ -392,7 +392,7 @@ function nfaToDfa(nfa: NfaNode): DfaNode {
function getClosure(nodes: NfaNode[]): DfaNode {
const closure: NfaNode[] = [];
const stack: NfaNode[] = [];
const symbols: string[] = [];
const symbols: (string | [string])[] = [];
let type = '';
let top: NfaNode | string;

Expand Down Expand Up @@ -447,7 +447,7 @@ function nfaToDfa(nfa: NfaNode): DfaNode {
};
}

function getClosedMove(closure: DfaNode, symbol: string): DfaNode {
function getClosedMove(closure: DfaNode, symbol: string | [string]): DfaNode {
const nexts: NfaNode[] = [];

for (const node of closure.items) {
Expand Down Expand Up @@ -514,7 +514,7 @@ function nfaToDfa(nfa: NfaNode): DfaNode {
* @param {object} dfa @see nfaToDfa(), the function assumes that the given DFA is valid.
* @return {object} dfa Returns the first element of the minimum DFA.
*/
function minDfa(dfa) {
function minDfa(dfa: DfaNode) {
'use strict';
function getReverseEdges(start: DfaNode): [string[], Record<string, DfaNode>, Record<string, Record<string, (string | number)[]>>] {
const symbols: Record<string, boolean> = {}; // The input alphabet
Expand Down Expand Up @@ -724,8 +724,8 @@ function minDfa(dfa) {
});

Object.keys(edges).forEach((from) => {
Object.keys(edges[from]).forEach((to) => {
const symbol = JSON.stringify(Object.keys(edges[from][to]).sort());
Object.keys(edges[Number(from)]).forEach((to) => {
const symbol = JSON.stringify(Object.keys(edges[Number(from)][Number(to)]).sort());
nodes[parseInt(from)].symbols.push(symbol);
nodes[parseInt(from)].edges.push([symbol, nodes[parseInt(to)]]);
nodes[parseInt(from)].trans[symbol] = nodes[parseInt(to)];
Expand Down Expand Up @@ -767,12 +767,13 @@ function toNature(col: string): number {

function regexToDfa(regex: string): string {
const nfa = regexToNfa(regex);

console.log(nfa);
if (typeof nfa === 'string') {
return nfa;
}

const dfa = minDfa(nfaToDfa(nfa));
console.log(dfa);
const states: Record<string, DfaNode> = {};
const nodes: DfaNode[] = [];
const stack: DfaNode[] = [dfa];
Expand Down Expand Up @@ -809,7 +810,7 @@ function regexToDfa(regex: string): string {
}
graph[node.nature - 1] = curr;
}
// console.log(`graph: ${JSON.stringify(graph, null, 2)}`);
console.log(`graph: ${JSON.stringify(graph, null, 2)}`);

return JSON.stringify(graph);
}
Expand Down
Loading

0 comments on commit 818eb95

Please sign in to comment.