package sqlgen import ( "errors" "os" "strings" ) func parsePath(driver, filePath string) (*schema, error) { fileBytes, err := os.ReadFile(filePath) if err != nil { return nil, err } return parseBytes(driver, fileBytes) } func parseBytes(driver string, fileBytes []byte) (*schema, error) { s := string(fileBytes) for _, c := range []string{",", "(", ")", ";"} { s = strings.ReplaceAll(s, c, " "+c+" ") } var ( tokens = strings.Fields(s) schema = &schema{} err error ) for len(tokens) > 0 { switch tokens[0] { case "TABLE": tokens, err = parseTable(driver, schema, tokens) if err != nil { return nil, err } default: return nil, errors.New("invalid token: " + tokens[0]) } } return schema, nil } func parseTable(driver string, schema *schema, tokens []string) ([]string, error) { tokens = tokens[1:] if len(tokens) < 3 { return tokens, errors.New("incomplete table definition") } if tokens[1] != "OF" { return tokens, errors.New("expected OF in table definition") } table := &table{ driver: driver, Name: tokens[0], Type: tokens[2], } schema.Tables = append(schema.Tables, table) tokens = tokens[3:] if len(tokens) == 0 { return tokens, errors.New("missing table definition body") } for len(tokens) > 0 { switch tokens[0] { case "NoInsert": table.NoInsert = true tokens = tokens[1:] case "NoUpdate": table.NoUpdate = true tokens = tokens[1:] case "NoDelete": table.NoDelete = true tokens = tokens[1:] case "(": return parseTableBody(table, tokens[1:]) default: return tokens, errors.New("unexpected token in table definition: " + tokens[0]) } } return tokens, errors.New("incomplete table definition") } func parseTableBody(table *table, tokens []string) ([]string, error) { var err error for len(tokens) > 0 && tokens[0] != ";" { tokens, err = parseTableColumn(table, tokens) if err != nil { return tokens, err } } if len(tokens) < 1 || tokens[0] != ";" { return tokens, errors.New("incomplete table column definitions") } return tokens[1:], nil } func parseTableColumn(table *table, tokens []string) ([]string, error) { if len(tokens) < 2 { return tokens, errors.New("incomplete column definition") } column := &column{ Name: tokens[0], Type: tokens[1], SqlName: tokens[0], } table.Columns = append(table.Columns, column) tokens = tokens[2:] for len(tokens) > 0 && tokens[0] != "," && tokens[0] != ")" { switch tokens[0] { case "AS": if len(tokens) < 2 { return tokens, errors.New("incomplete AS clause in column definition") } column.Name = tokens[1] tokens = tokens[2:] case "PK": column.PK = true tokens = tokens[1:] case "NoInsert": column.NoInsert = true tokens = tokens[1:] case "NoUpdate": column.NoUpdate = true tokens = tokens[1:] default: return tokens, errors.New("unexpected token in column definition: " + tokens[0]) } } if len(tokens) == 0 { return tokens, errors.New("incomplete column definition") } return tokens[1:], nil }