summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2026-10-16 09:03:53 +0100
committerMichael Williamson <mike@zwobble.org>2026-10-16 09:03:53 +0100
commitb0c668a96bc8da225d7a0c35dfd7ce4178ebb7c4 (patch)
tree717467f7c153efec813d7926abd922e9845133f0
parent77c708cbb7a4fb49db50a8917bdcdd777eff6ccb (diff)
Add SQL AST for CREATE TABLE statements
-rw-r--r--hobgoblin/src/output/lang/sql/ast.hob17
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/output/lang/sql/SqlWriter.java82
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/output/lang/sql/ast/SqlColumnDefinition.java46
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/output/lang/sql/ast/SqlCreateTableStatement.java54
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/output/lang/sql/ast/SqlIdentifier.java32
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/output/lang/sql/ast/SqlStatement.java18
-rw-r--r--src/test/java/org/zwobble/hobgoblin/compiler/output/lang/sql/SqlWriterTests.java58
-rw-r--r--src/test/java/org/zwobble/hobgoblin/compiler/output/lang/sql/ast/SqlColumnDefinitionMatcher.java47
-rw-r--r--src/test/java/org/zwobble/hobgoblin/compiler/output/lang/sql/ast/SqlCreateTableStatementMatcher.java47
-rw-r--r--src/test/java/org/zwobble/hobgoblin/compiler/output/lang/sql/ast/SqlIdentifierMatcher.java41
10 files changed, 442 insertions, 0 deletions
diff --git a/hobgoblin/src/output/lang/sql/ast.hob b/hobgoblin/src/output/lang/sql/ast.hob
new file mode 100644
index 0000000..9a51e38
--- /dev/null
+++ b/hobgoblin/src/output/lang/sql/ast.hob
@@ -0,0 +1,17 @@
+sum SqlStatement {
+ variant SqlCreateTableStatement;
+}
+
+struct SqlCreateTableStatement {
+ field name: SqlIdentifier;
+ field columns: List[SqlColumnDefinition];
+}
+
+struct SqlColumnDefinition {
+ field name: SqlIdentifier;
+ field typeName: SqlIdentifier;
+}
+
+struct SqlIdentifier {
+ field value: String;
+}
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/sql/SqlWriter.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/sql/SqlWriter.java
new file mode 100644
index 0000000..20b28c3
--- /dev/null
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/sql/SqlWriter.java
@@ -0,0 +1,82 @@
+package org.zwobble.hobgoblin.compiler.output.lang.sql;
+
+import org.zwobble.hobgoblin.compiler.output.CodeWriter;
+import org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinition;
+import org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatement;
+import org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier;
+import org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlStatement;
+
+import java.io.IOException;
+import java.nio.file.Path;
+
+import static org.zwobble.hobgoblin.compiler.output.CodeWriter.writeWithSeparator;
+
+public class SqlWriter {
+ private static final String LINE_COMMENT_START = "--";
+
+ public interface Write {
+ void write(SqlWriter writer) throws IOException;
+ }
+
+ public static void writeTo(Path path, Write write) throws IOException {
+ CodeWriter.writeTo(
+ path,
+ LINE_COMMENT_START,
+ writer -> write.write(new SqlWriter(writer))
+ );
+ }
+
+ public static void writeTo(CodeWriter.CodeWriterFile file, Write write) throws IOException {
+ CodeWriter.writeTo(
+ file,
+ LINE_COMMENT_START,
+ writer -> write.write(new SqlWriter(writer))
+ );
+ }
+
+ private final CodeWriter writer;
+
+ public SqlWriter(CodeWriter writer) {
+ this.writer = writer;
+ }
+
+ void writeStatement(SqlStatement statement) throws IOException {
+ switch (statement) {
+ case SqlCreateTableStatement createTableStatement -> {
+ writeCreateTableStatement(createTableStatement);
+ }
+ }
+ }
+
+ private void writeCreateTableStatement(SqlCreateTableStatement createTableStatement) throws IOException {
+ this.writer.write("CREATE TABLE ");
+ this.writeIdentifier(createTableStatement.name());
+ this.writer.write(" (");
+ this.writer.newLine();
+ this.writer.indent();
+
+ writeWithSeparator(
+ createTableStatement.columns(),
+ column -> writeColumnDefinition(column),
+ () -> {
+ this.writer.write(",");
+ this.writer.newLine();
+ }
+ );
+
+ this.writer.dedent();
+ this.writer.newLine();
+ this.writer.write(");");
+ }
+
+ private void writeColumnDefinition(SqlColumnDefinition column) throws IOException {
+ this.writeIdentifier(column.name());
+ this.writer.write(" ");
+ this.writeIdentifier(column.typeName());
+ }
+
+ private void writeIdentifier(SqlIdentifier name) throws IOException {
+ // TODO: handle escaping
+ this.writer.write(name.value());
+ }
+}
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/sql/ast/SqlColumnDefinition.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/sql/ast/SqlColumnDefinition.java
new file mode 100644
index 0000000..837da77
--- /dev/null
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/sql/ast/SqlColumnDefinition.java
@@ -0,0 +1,46 @@
+// Generated by hobgoblin.
+
+package org.zwobble.hobgoblin.compiler.output.lang.sql.ast;
+
+// Custom area start: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinition imports
+// Custom area end: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinition imports
+
+public record SqlColumnDefinition(
+ org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier name,
+ org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier typeName
+) {
+ public static org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinition.Builder arbitrary() {
+ return new org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinition.Builder(org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier.arbitrary().build(), org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier.arbitrary().build());
+ }
+
+ public record Builder(
+ org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier name,
+ org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier typeName
+ ) {
+ public org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinition build() {
+ return new org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinition(name, typeName);
+ }
+
+ public org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinition.Builder withName(org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier name) {
+ return new org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinition.Builder(name, typeName);
+ }
+
+ public org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinition.Builder withName(org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier.Builder name) {
+ return new org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinition.Builder(name.build(), typeName);
+ }
+
+ public org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinition.Builder withTypeName(org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier typeName) {
+ return new org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinition.Builder(name, typeName);
+ }
+
+ public org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinition.Builder withTypeName(org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier.Builder typeName) {
+ return new org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinition.Builder(name, typeName.build());
+ }
+
+ // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinition.Builder body
+ // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinition.Builder body
+ }
+
+ // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinition body
+ // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinition body
+}
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/sql/ast/SqlCreateTableStatement.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/sql/ast/SqlCreateTableStatement.java
new file mode 100644
index 0000000..a5fec23
--- /dev/null
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/sql/ast/SqlCreateTableStatement.java
@@ -0,0 +1,54 @@
+// Generated by hobgoblin.
+
+package org.zwobble.hobgoblin.compiler.output.lang.sql.ast;
+
+// Custom area start: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatement imports
+// Custom area end: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatement imports
+
+public record SqlCreateTableStatement(
+ org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier name,
+ java.util.List<org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinition> columns
+) implements org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlStatement {
+ public static org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatement.Builder arbitrary() {
+ return new org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatement.Builder(org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier.arbitrary().build(), java.util.List.of());
+ }
+
+ public record Builder(
+ org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier name,
+ java.util.List<org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinition> columns
+ ) implements org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlStatement.Builder {
+ public org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatement build() {
+ return new org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatement(name, columns);
+ }
+
+ public org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatement.Builder withName(org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier name) {
+ return new org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatement.Builder(name, columns);
+ }
+
+ public org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatement.Builder withName(org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier.Builder name) {
+ return new org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatement.Builder(name.build(), columns);
+ }
+
+ public org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatement.Builder withColumns(java.util.List<org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinition> columns) {
+ return new org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatement.Builder(name, columns);
+ }
+
+ public org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatement.Builder addColumn(org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinition column) {
+ var columns = new java.util.ArrayList<org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinition>(this.columns);
+ columns.add(column);
+ return new org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatement.Builder(name, columns);
+ }
+
+ public org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatement.Builder addColumn(org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinition.Builder column) {
+ var columns = new java.util.ArrayList<org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinition>(this.columns);
+ columns.add(column.build());
+ return new org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatement.Builder(name, columns);
+ }
+
+ // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatement.Builder body
+ // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatement.Builder body
+ }
+
+ // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatement body
+ // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatement body
+}
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/sql/ast/SqlIdentifier.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/sql/ast/SqlIdentifier.java
new file mode 100644
index 0000000..9acc2e4
--- /dev/null
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/sql/ast/SqlIdentifier.java
@@ -0,0 +1,32 @@
+// Generated by hobgoblin.
+
+package org.zwobble.hobgoblin.compiler.output.lang.sql.ast;
+
+// Custom area start: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier imports
+// Custom area end: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier imports
+
+public record SqlIdentifier(
+ String value
+) {
+ public static org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier.Builder arbitrary() {
+ return new org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier.Builder("");
+ }
+
+ public record Builder(
+ String value
+ ) {
+ public org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier build() {
+ return new org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier(value);
+ }
+
+ public org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier.Builder withValue(String value) {
+ return new org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier.Builder(value);
+ }
+
+ // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier.Builder body
+ // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier.Builder body
+ }
+
+ // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier body
+ // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier body
+}
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/sql/ast/SqlStatement.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/sql/ast/SqlStatement.java
new file mode 100644
index 0000000..0f90dc1
--- /dev/null
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/sql/ast/SqlStatement.java
@@ -0,0 +1,18 @@
+// Generated by hobgoblin.
+
+package org.zwobble.hobgoblin.compiler.output.lang.sql.ast;
+
+// Custom area start: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlStatement imports
+// Custom area end: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlStatement imports
+
+public sealed interface SqlStatement permits org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatement {
+ public interface Builder {
+ public org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlStatement build();
+
+ // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlStatement.Builder body
+ // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlStatement.Builder body
+ }
+
+ // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlStatement body
+ // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlStatement body
+}
diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/sql/SqlWriterTests.java b/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/sql/SqlWriterTests.java
new file mode 100644
index 0000000..5edf06c
--- /dev/null
+++ b/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/sql/SqlWriterTests.java
@@ -0,0 +1,58 @@
+package org.zwobble.hobgoblin.compiler.output.lang.sql;
+
+import org.junit.jupiter.api.Test;
+import org.zwobble.hobgoblin.compiler.output.CodeWriter;
+import org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinition;
+import org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatement;
+import org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.Optional;
+
+import static org.zwobble.precisely.AssertThat.assertThat;
+import static org.zwobble.precisely.Matchers.equalTo;
+
+public class SqlWriterTests {
+ @Test
+ public void createTableStatement() throws IOException {
+ var sql = SqlCreateTableStatement.arbitrary()
+ .withName(id("authors"))
+ .addColumn(SqlColumnDefinition.arbitrary()
+ .withName(id("id"))
+ .withTypeName(id("INT"))
+ )
+ .addColumn(SqlColumnDefinition.arbitrary()
+ .withName(id("name"))
+ .withTypeName(id("TEXT"))
+ )
+ .build();
+
+ var string = write(writer -> writer.writeStatement(sql));
+
+ assertThat(string, equalTo("""
+ CREATE TABLE authors (
+ id INT,
+ name TEXT
+ );"""
+ ));
+ }
+
+ private String write(SqlWriter.Write write) throws IOException {
+ return write(write, Optional.empty());
+ }
+
+ private String write(SqlWriter.Write write, Optional<String> originalContents) throws IOException {
+ var stringWriter = new StringWriter();
+ SqlWriter.writeTo(
+ new CodeWriter.InMemoryCodeWriterFile(originalContents, stringWriter),
+ write
+ );
+ return stringWriter.toString();
+ }
+
+ private SqlIdentifier id(String value) {
+ return new SqlIdentifier(value);
+
+ }
+}
diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/sql/ast/SqlColumnDefinitionMatcher.java b/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/sql/ast/SqlColumnDefinitionMatcher.java
new file mode 100644
index 0000000..cbe2ea9
--- /dev/null
+++ b/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/sql/ast/SqlColumnDefinitionMatcher.java
@@ -0,0 +1,47 @@
+// Generated by hobgoblin.
+
+package org.zwobble.hobgoblin.compiler.output.lang.sql.ast;
+
+// Custom area start: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinitionMatcher imports
+// Custom area end: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinitionMatcher imports
+
+public final class SqlColumnDefinitionMatcher implements org.zwobble.precisely.Matcher<java.lang.Object> {
+ public static org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinitionMatcher isSqlColumnDefinition() {
+ return new org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinitionMatcher(java.util.List.of());
+ }
+
+ private final java.util.List<org.zwobble.precisely.Matcher<? super org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinition>> submatchers;
+
+ private SqlColumnDefinitionMatcher(
+ java.util.List<org.zwobble.precisely.Matcher<? super org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinition>> submatchers
+ ) {
+ this.submatchers = submatchers;
+ }
+
+ public org.zwobble.precisely.MatchResult match(java.lang.Object actual) {
+ return this.toMatcher().match(actual);
+ }
+
+ public org.zwobble.precisely.TextTree describe() {
+ return this.toMatcher().describe();
+ }
+
+ private org.zwobble.precisely.Matcher<java.lang.Object> toMatcher() {
+ return org.zwobble.precisely.Matchers.instanceOf(org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinition.class, this.submatchers);
+ }
+
+ public org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinitionMatcher withName(org.zwobble.precisely.Matcher<? super org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier> name) {
+ var submatchers = new java.util.ArrayList<org.zwobble.precisely.Matcher<? super org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinition>>(this.submatchers);
+ submatchers.add(org.zwobble.precisely.Matchers.has("name", org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinition::name, (org.zwobble.precisely.Matcher) name));
+ return new org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinitionMatcher(submatchers);
+ }
+
+ public org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinitionMatcher withTypeName(org.zwobble.precisely.Matcher<? super org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier> typeName) {
+ var submatchers = new java.util.ArrayList<org.zwobble.precisely.Matcher<? super org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinition>>(this.submatchers);
+ submatchers.add(org.zwobble.precisely.Matchers.has("typeName", org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinition::typeName, (org.zwobble.precisely.Matcher) typeName));
+ return new org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinitionMatcher(submatchers);
+ }
+
+ // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinitionMatcher body
+ // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinitionMatcher body
+}
diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/sql/ast/SqlCreateTableStatementMatcher.java b/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/sql/ast/SqlCreateTableStatementMatcher.java
new file mode 100644
index 0000000..d6c8d57
--- /dev/null
+++ b/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/sql/ast/SqlCreateTableStatementMatcher.java
@@ -0,0 +1,47 @@
+// Generated by hobgoblin.
+
+package org.zwobble.hobgoblin.compiler.output.lang.sql.ast;
+
+// Custom area start: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatementMatcher imports
+// Custom area end: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatementMatcher imports
+
+public final class SqlCreateTableStatementMatcher implements org.zwobble.precisely.Matcher<java.lang.Object> {
+ public static org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatementMatcher isSqlCreateTableStatement() {
+ return new org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatementMatcher(java.util.List.of());
+ }
+
+ private final java.util.List<org.zwobble.precisely.Matcher<? super org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatement>> submatchers;
+
+ private SqlCreateTableStatementMatcher(
+ java.util.List<org.zwobble.precisely.Matcher<? super org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatement>> submatchers
+ ) {
+ this.submatchers = submatchers;
+ }
+
+ public org.zwobble.precisely.MatchResult match(java.lang.Object actual) {
+ return this.toMatcher().match(actual);
+ }
+
+ public org.zwobble.precisely.TextTree describe() {
+ return this.toMatcher().describe();
+ }
+
+ private org.zwobble.precisely.Matcher<java.lang.Object> toMatcher() {
+ return org.zwobble.precisely.Matchers.instanceOf(org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatement.class, this.submatchers);
+ }
+
+ public org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatementMatcher withName(org.zwobble.precisely.Matcher<? super org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier> name) {
+ var submatchers = new java.util.ArrayList<org.zwobble.precisely.Matcher<? super org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatement>>(this.submatchers);
+ submatchers.add(org.zwobble.precisely.Matchers.has("name", org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatement::name, (org.zwobble.precisely.Matcher) name));
+ return new org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatementMatcher(submatchers);
+ }
+
+ public org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatementMatcher withColumns(org.zwobble.precisely.Matcher<? super java.util.List<org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlColumnDefinition>> columns) {
+ var submatchers = new java.util.ArrayList<org.zwobble.precisely.Matcher<? super org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatement>>(this.submatchers);
+ submatchers.add(org.zwobble.precisely.Matchers.has("columns", org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatement::columns, (org.zwobble.precisely.Matcher) columns));
+ return new org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatementMatcher(submatchers);
+ }
+
+ // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatementMatcher body
+ // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlCreateTableStatementMatcher body
+}
diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/sql/ast/SqlIdentifierMatcher.java b/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/sql/ast/SqlIdentifierMatcher.java
new file mode 100644
index 0000000..b96c624
--- /dev/null
+++ b/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/sql/ast/SqlIdentifierMatcher.java
@@ -0,0 +1,41 @@
+// Generated by hobgoblin.
+
+package org.zwobble.hobgoblin.compiler.output.lang.sql.ast;
+
+// Custom area start: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifierMatcher imports
+// Custom area end: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifierMatcher imports
+
+public final class SqlIdentifierMatcher implements org.zwobble.precisely.Matcher<java.lang.Object> {
+ public static org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifierMatcher isSqlIdentifier() {
+ return new org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifierMatcher(java.util.List.of());
+ }
+
+ private final java.util.List<org.zwobble.precisely.Matcher<? super org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier>> submatchers;
+
+ private SqlIdentifierMatcher(
+ java.util.List<org.zwobble.precisely.Matcher<? super org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier>> submatchers
+ ) {
+ this.submatchers = submatchers;
+ }
+
+ public org.zwobble.precisely.MatchResult match(java.lang.Object actual) {
+ return this.toMatcher().match(actual);
+ }
+
+ public org.zwobble.precisely.TextTree describe() {
+ return this.toMatcher().describe();
+ }
+
+ private org.zwobble.precisely.Matcher<java.lang.Object> toMatcher() {
+ return org.zwobble.precisely.Matchers.instanceOf(org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier.class, this.submatchers);
+ }
+
+ public org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifierMatcher withValue(org.zwobble.precisely.Matcher<? super String> value) {
+ var submatchers = new java.util.ArrayList<org.zwobble.precisely.Matcher<? super org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier>>(this.submatchers);
+ submatchers.add(org.zwobble.precisely.Matchers.has("value", org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier::value, (org.zwobble.precisely.Matcher) value));
+ return new org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifierMatcher(submatchers);
+ }
+
+ // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifierMatcher body
+ // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifierMatcher body
+}