Skip to content

Commit

Permalink
Implement visitor for printer (linting) (#7)
Browse files Browse the repository at this point in the history
Co-authored-by: Jongchan Choi <[email protected]>
  • Loading branch information
hyp3rflow and disjukr authored Mar 3, 2022
1 parent 02f4df5 commit 4c2281a
Show file tree
Hide file tree
Showing 7 changed files with 1,187 additions and 2 deletions.
2 changes: 1 addition & 1 deletion ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export interface Key {
export interface TailRuleFormPatternRule {
comment?: Token;
key: Key;
value: TailRulePatternValue[];
value: TailRulePatternValue[] | null;
array: boolean;
}
export interface TailRulePatternValue {
Expand Down
2 changes: 1 addition & 1 deletion compile/js-url-checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ export function compile(
write(`{
const values = form.getAll(${compileKeyToken(key)});
if (values.every(
value => ${compileTailRulePattern("value", value)}
value => ${compileTailRulePattern("value", value ?? [])}
)) {
formResult[${compileKeyToken(key)}] = values;
} else {
Expand Down
100 changes: 100 additions & 0 deletions stringifier/formatter.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { parse } from "../index.ts";
import { assertEquals } from "https://deno.land/[email protected]/testing/asserts.ts";
import format from "./formatter.ts";

Deno.test("formatter", () => {
const fixture = `
scheme:example1.com/foo/bar/baz {
? match
/web-path=(?<path>.*)/
# match id-1
| id-2
| /id-3/
}
/**
* foo
*/
scheme:example2.com/path/[param1]/[param2] {
/**
* bar
*/
? form {
/**
* baz
*/
'' = ''
a
b
param1 = exact | match | value
param2 = /^[0-9]+$/
param3 [] = /^[a-z]+$/i
}
# match /id/
}
scheme:[email protected]:4321 {
? form {'a' = /.*/
'b' = /.*/
'c-d' = /.*/
'/' = /.*/
'?' = /.*/
'f/' = /.*/
'g' = /.*/
'h' = /.*/
}
}`;

const schema = parse(fixture);
if (!schema) throw new Error("No schema");
const formatted = format(schema);
console.log(formatted);
assertEquals(
formatted,
`scheme:example1.com/foo/bar/baz {
? match /web-path=(?<path>.*)/
# match
| id-1
| id-2
| /id-3/
}
/**
* foo
*/
scheme:example2.com/path/[param1]/[param2] {
/**
* bar
*/
? form {
/**
* baz
*/
'' = ''
a
b
param1 = exact | match | value
param2 = /^[0-9]+$/
param3 [] = /^[a-z]+$/i
}
# match /id/
}
scheme:[email protected]:4321 {
? form {
'a' = /.*/
'b' = /.*/
'c-d' = /.*/
'/' = /.*/
'?' = /.*/
'f/' = /.*/
'g' = /.*/
'h' = /.*/
}
}
`,
);
});
118 changes: 118 additions & 0 deletions stringifier/formatter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import * as ast from "../ast.ts";
import { Visitor, visitor as defaultVisitor } from "../visitor/index.ts";
import { createPrinter } from "./printer.ts";

export default function format(ast: ast.Urichk): string {
const printer = createPrinter();
const formatter: Visitor = {
...defaultVisitor,
visitToken(visitor, node) {
printer.print(node.text);
},
visitHead(visitor, node) {
defaultVisitor.visitHead(visitor, node);
printer.print(" ");
},
visitUserinfo(visitor, node) {
defaultVisitor.visitUserinfo(visitor, node);
printer.print("@");
},
visitScheme(visitor, node) {
defaultVisitor.visitScheme(visitor, node);
printer.print(":");
},
visitPort(visitor, node) {
printer.print(":");
defaultVisitor.visitPort(visitor, node);
},
visitPathFragment(visitor, node) {
printer.print("/");
defaultVisitor.visitPathFragment(visitor, node);
},
visitParamPathFragment(visitor, node) {
printer.print("[");
defaultVisitor.visitParamPathFragment(visitor, node);
printer.print("]");
},
visitTail(visitor, node) {
printer.print("{");
printer.indent();
for (const rule of node) {
printer.print("\n");
visitor.visitTailRule(visitor, rule);
printer.print("\n");
}
printer.dedent();
printer.println("}\n");
},
visitTailRule(visitor, node) {
printer.printIndent();
defaultVisitor.visitTailRule(visitor, node);
},
visitTailRuleMatch(visitor, node) {
const { matchType, pattern } = node;
visitor.visitMatchType(visitor, matchType);
if (pattern.length > 1) {
printer.indent();
for (const value of pattern) {
printer.print("\n");
printer.printIndent();
printer.print("| ");
visitor.visitTailRulePatternValue(visitor, value);
}
printer.dedent();
} else {
for (const value of pattern) {
visitor.visitTailRulePatternValue(visitor, value);
}
}
},
visitTailRuleForm(visitor, node) {
const { matchType, pattern } = node;
visitor.visitMatchType(visitor, matchType);
printer.print("{\n");
printer.indent();
for (const rule of pattern) {
visitor.visitTailRuleFormPatternRule(visitor, rule);
}
printer.dedent();
printer.printIndent();
printer.print("}");
},
visitTailRuleFormPatternRule(visitor, node) {
printer.printIndent();
const { comment, key, value, array } = node;
if (comment) visitor.visitComment(visitor, comment);
visitor.visitKey(visitor, key);
visitor.visitArrayToken(visitor, array);
if (value) {
printer.print(" ");
printer.print("=");
printer.print(" ");
value.forEach((patternValue, index) => {
if (index > 0) printer.print(" | ");
visitor.visitTailRulePatternValue(visitor, patternValue);
});
}
printer.print("\n");
},
visitArrayToken(visitor, node) {
if (node === true) printer.print(" []");
},
visitTailType(visitor, node) {
defaultVisitor.visitTailType(visitor, node);
printer.print(" ");
},
visitMatchType(visitor, node) {
defaultVisitor.visitMatchType(visitor, node);
printer.print(" ");
},
visitComment(visitor, node) {
defaultVisitor.visitComment(visitor, node);
printer.print("\n");
printer.printIndent();
},
};
formatter.visitUrichk(formatter, ast);
return printer.done();
}
39 changes: 39 additions & 0 deletions stringifier/printer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
export interface Printer {
indent(): void;
dedent(): void;
print(text: string): void;
printIndent(): void;
println(line: string): void;
done(): string;
}

export interface CreatePrinterConfig {
space?: string;
}
export function createPrinter(config?: CreatePrinterConfig): Printer {
const { space = " " } = { ...config };
const buffer: string[] = [];
let _indent = 0;
return {
indent() {
++_indent;
},
dedent() {
--_indent;
},
print(text) {
buffer.push(text);
},
printIndent() {
buffer.push(space.repeat(_indent));
},
println(line) {
buffer.push(space.repeat(_indent));
buffer.push(line);
buffer.push("\n");
},
done() {
return buffer.join("");
},
};
}
Loading

0 comments on commit 4c2281a

Please sign in to comment.