Task 045: .ATG File Format
Task 045: .ATG File Format
The .ATG file extension is associated with multiple contexts, but no comprehensive, standardized specification is publicly available for a single, unified .ATG file format. Based on available information, the .ATG extension is primarily linked to two distinct uses: Coco/R Attributed Grammar Files (used in compiler generation) and Netmino Files (an obsolete address book format for iOS). Additionally, there are references to .ATG files in Oracle ATG Web Commerce (configuration files), Minecraft (Alternate Terrain Generation), and FlightGear (deprecated ASCII terrain files). However, none of these sources provide a detailed, intrinsic file system specification for .ATG files, and the format appears context-dependent. For this task, I’ll assume the .ATG file is a Coco/R Attributed Grammar File, as it’s the most commonly referenced developer-related format, and hypothesize a text-based structure with properties typical of attributed grammar files. Since no explicit specification exists, I’ll define a reasonable set of properties and implement classes to handle a simplified .ATG file structure.
1. List of Properties of the .ATG File Format Intrinsic to Its File System
Without a formal specification, I’ll infer properties based on the Coco/R Attributed Grammar File context, where .ATG files are text-based and contain grammar definitions with attributes. These files are typically used to define syntax for compilers, with properties like production rules, tokens, and attributes. The intrinsic properties relevant to the file system include:
- File Extension:
.atg
- File Type: Text-based (ASCII or UTF-8 encoded)
- Structure: Structured text, typically containing sections for:
- Header: Compiler or character set declarations (e.g.,
COMPILER <name>
). - Characters: Definitions of character sets (e.g.,
CHARACTERS letter = 'a'..'z' + 'A'..'Z'.
). - Tokens: Regular expressions for lexical tokens (e.g.,
TOKENS ident = letter {letter | digit}.
). - Productions: Grammar production rules with attributes (e.g.,
ProductionName = term1 term2.
). - Comments: Support for comments (e.g.,
//
or/* */
). - Line Termination: Standard line endings (
\n
for Unix-like systems,\r\n
for Windows). - Encoding: Typically UTF-8 or ASCII, supporting Unicode via escape sequences (e.g.,
\u002c
). - Size: Variable, typically small (kilobytes) for grammar files.
- Delimiter: Whitespace, newlines, or specific symbols (e.g.,
=
for assignments,.
for rule termination). - File Access: Sequential read/write, as it’s a text file.
- Versioning: No explicit versioning in the format itself, but may include a compiler version in the header.
- Error Handling: Syntax errors are reported by Coco/R during parsing, not embedded in the file.
These properties are derived from the Coco/R context and general text-based file characteristics. If the intended .ATG format differs (e.g., Netmino or Oracle ATG), please clarify for a tailored specification.
2. Python Class for .ATG File Handling
Below is a Python class that opens, reads, writes, and prints properties of a simplified .ATG file, assuming it’s a Coco/R Attributed Grammar File with sections for header, characters, tokens, and productions.
import re
class ATGFile:
def __init__(self, filepath):
self.filepath = filepath
self.properties = {
"extension": ".atg",
"file_type": "text",
"encoding": "utf-8",
"header": "",
"characters": [],
"tokens": [],
"productions": [],
"size": 0,
"line_ending": "\n"
}
def read(self):
"""Read and decode the .ATG file."""
try:
with open(self.filepath, 'r', encoding=self.properties["encoding"]) as file:
content = file.read()
self.properties["size"] = len(content.encode('utf-8'))
# Parse sections using regex (simplified)
header_match = re.match(r'COMPILER\s+(\w+)', content, re.MULTILINE)
if header_match:
self.properties["header"] = header_match.group(1)
char_matches = re.findall(r'CHARACTERS\s+(\w+)\s*=\s*[^.]+\.', content, re.MULTILINE)
self.properties["characters"] = char_matches
token_matches = re.findall(r'TOKENS\s+(\w+)\s*=\s*[^.]+\.', content, re.MULTILINE)
self.properties["tokens"] = token_matches
prod_matches = re.findall(r'PRODUCTIONS\s+([\s\S]+?)END\s+\w+\.', content, re.MULTILINE)
self.properties["productions"] = prod_matches[0].strip().split('\n') if prod_matches else []
self.properties["line_ending"] = "\r\n" if "\r\n" in content else "\n"
except FileNotFoundError:
print(f"Error: File {self.filepath} not found.")
except Exception as e:
print(f"Error reading file: {e}")
def write(self, header, characters, tokens, productions):
"""Write properties to a new .ATG file."""
try:
with open(self.filepath, 'w', encoding=self.properties["encoding"]) as file:
file.write(f"COMPILER {header}{self.properties['line_ending']}")
file.write(f"CHARACTERS{self.properties['line_ending']}")
for char in characters:
file.write(f"{char}.{self.properties['line_ending']}")
file.write(f"TOKENS{self.properties['line_ending']}")
for token in tokens:
file.write(f"{token}.{self.properties['line_ending']}")
file.write(f"PRODUCTIONS{self.properties['line_ending']}")
for prod in productions:
file.write(f"{prod}{self.properties['line_ending']}")
file.write(f"END {header}.{self.properties['line_ending']}")
self.properties["header"] = header
self.properties["characters"] = characters
self.properties["tokens"] = tokens
self.properties["productions"] = productions
self.properties["size"] = len(open(self.filepath, 'r', encoding='utf-8').read().encode('utf-8'))
except Exception as e:
print(f"Error writing file: {e}")
def print_properties(self):
"""Print all properties to console."""
for key, value in self.properties.items():
print(f"{key}: {value}")
# Example usage
if __name__ == "__main__":
atg = ATGFile("example.atg")
atg.read()
atg.print_properties()
# Example write
atg.write(
header="ExampleGrammar",
characters=["letter = 'a'..'z' + 'A'..'Z'"],
tokens=["ident = letter {letter | digit}"],
productions=["Start = ident ."]
)
atg.print_properties()
3. Java Class for .ATG File Handling
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ATGFile {
private String filepath;
private String extension = ".atg";
private String fileType = "text";
private String encoding = "UTF-8";
private String header = "";
private List<String> characters = new ArrayList<>();
private List<String> tokens = new ArrayList<>();
private List<String> productions = new ArrayList<>();
private long size = 0;
private String lineEnding = "\n";
public ATGFile(String filepath) {
this.filepath = filepath;
}
public void read() {
try {
String content = new String(Files.readAllBytes(Paths.get(filepath)), encoding);
size = content.getBytes(encoding).length;
// Parse sections using regex
Pattern headerPattern = Pattern.compile("COMPILER\\s+(\\w+)");
Matcher headerMatcher = headerPattern.matcher(content);
if (headerMatcher.find()) {
header = headerMatcher.group(1);
}
Pattern charPattern = Pattern.compile("CHARACTERS\\s+(\\w+\\s*=\\s*[^.]+\\.)", Pattern.MULTILINE);
Matcher charMatcher = charPattern.matcher(content);
while (charMatcher.find()) {
characters.add(charMatcher.group(1));
}
Pattern tokenPattern = Pattern.compile("TOKENS\\s+(\\w+\\s*=\\s*[^.]+\\.)", Pattern.MULTILINE);
Matcher tokenMatcher = tokenPattern.matcher(content);
while (tokenMatcher.find()) {
tokens.add(tokenMatcher.group(1));
}
Pattern prodPattern = Pattern.compile("PRODUCTIONS\\s+([\\s\\S]+?)END\\s+\\w+\\.", Pattern.MULTILINE);
Matcher prodMatcher = prodPattern.matcher(content);
if (prodMatcher.find()) {
productions = List.of(prodMatcher.group(1).trim().split("\n"));
}
lineEnding = content.contains("\r\n") ? "\r\n" : "\n";
} catch (IOException e) {
System.err.println("Error reading file: " + e.getMessage());
}
}
public void write(String header, List<String> characters, List<String> tokens, List<String> productions) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filepath, false))) {
writer.write("COMPILER " + header + lineEnding);
writer.write("CHARACTERS" + lineEnding);
for (String charDef : characters) {
writer.write(charDef + lineEnding);
}
writer.write("TOKENS" + lineEnding);
for (String token : tokens) {
writer.write(token + lineEnding);
}
writer.write("PRODUCTIONS" + lineEnding);
for (String prod : productions) {
writer.write(prod + lineEnding);
}
writer.write("END " + header + "." + lineEnding);
this.header = header;
this.characters = characters;
this.tokens = tokens;
this.productions = productions;
this.size = Files.size(Paths.get(filepath));
} catch (IOException e) {
System.err.println("Error writing file: " + e.getMessage());
}
}
public void printProperties() {
System.out.println("extension: " + extension);
System.out.println("file_type: " + fileType);
System.out.println("encoding: " + encoding);
System.out.println("header: " + header);
System.out.println("characters: " + characters);
System.out.println("tokens: " + tokens);
System.out.println("productions: " + productions);
System.out.println("size: " + size);
System.out.println("line_ending: " + lineEnding);
}
public static void main(String[] args) {
ATGFile atg = new ATGFile("example.atg");
atg.read();
atg.printProperties();
atg.write(
"ExampleGrammar",
List.of("letter = 'a'..'z' + 'A'..'Z'"),
List.of("ident = letter {letter | digit}"),
List.of("Start = ident .")
);
atg.printProperties();
}
}
4. JavaScript Class for .ATG File Handling
const fs = require('fs').promises;
class ATGFile {
constructor(filepath) {
this.filepath = filepath;
this.properties = {
extension: '.atg',
fileType: 'text',
encoding: 'utf-8',
header: '',
characters: [],
tokens: [],
productions: [],
size: 0,
lineEnding: '\n'
};
}
async read() {
try {
const content = await fs.readFile(this.filepath, this.properties.encoding);
this.properties.size = Buffer.from(content).length;
// Parse sections using regex
const headerMatch = content.match(/COMPILER\s+(\w+)/m);
if (headerMatch) {
this.properties.header = headerMatch[1];
}
const charMatches = content.match(/CHARACTERS\s+\w+\s*=\s*[^.]+\./gm);
this.properties.characters = charMatches || [];
const tokenMatches = content.match(/TOKENS\s+\w+\s*=\s*[^.]+\./gm);
this.properties.tokens = tokenMatches || [];
const prodMatch = content.match(/PRODUCTIONS\s+([\s\S]+?)END\s+\w+\./m);
if (prodMatch) {
this.properties.productions = prodMatch[1].trim().split('\n');
}
this.properties.lineEnding = content.includes('\r\n') ? '\r\n' : '\n';
} catch (error) {
console.error(`Error reading file: ${error.message}`);
}
}
async write(header, characters, tokens, productions) {
try {
let content = `COMPILER ${header}${this.properties.lineEnding}`;
content += `CHARACTERS${this.properties.lineEnding}`;
for (const char of characters) {
content += `${char}${this.properties.lineEnding}`;
}
content += `TOKENS${this.properties.lineEnding}`;
for (const token of tokens) {
content += `${token}${this.properties.lineEnding}`;
}
content += `PRODUCTIONS${this.properties.lineEnding}`;
for (const prod of productions) {
content += `${prod}${this.properties.lineEnding}`;
}
content += `END ${header}.${this.properties.lineEnding}`;
await fs.writeFile(this.filepath, content, this.properties.encoding);
this.properties.header = header;
this.properties.characters = characters;
this.properties.tokens = tokens;
this.properties.productions = productions;
this.properties.size = Buffer.from(content).length;
} catch (error) {
console.error(`Error writing file: ${error.message}`);
}
}
printProperties() {
for (const [key, value] of Object.entries(this.properties)) {
console.log(`${key}: ${value}`);
}
}
}
// Example usage
(async () => {
const atg = new ATGFile('example.atg');
await atg.read();
atg.printProperties();
await atg.write(
'ExampleGrammar',
["letter = 'a'..'z' + 'A'..'Z'"],
["ident = letter {letter | digit}"],
["Start = ident ."]
);
atg.printProperties();
})();
5. C Class (Struct-Based) for .ATG File Handling
Since C doesn’t have classes, I’ll use a struct with functions to emulate class-like behavior. This implementation assumes a POSIX environment for file handling.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <regex.h>
#define MAX_LINE 256
#define MAX_SECTIONS 100
typedef struct {
char* filepath;
char* extension;
char* file_type;
char* encoding;
char* header;
char* characters[MAX_SECTIONS];
char* tokens[MAX_SECTIONS];
char* productions[MAX_SECTIONS];
size_t char_count;
size_t token_count;
size_t prod_count;
long size;
char* line_ending;
} ATGFile;
ATGFile* ATGFile_create(const char* filepath) {
ATGFile* atg = (ATGFile*)malloc(sizeof(ATGFile));
atg->filepath = strdup(filepath);
atg->extension = ".atg";
atg->file_type = "text";
atg->encoding = "UTF-8";
atg->header = "";
atg->char_count = 0;
atg->token_count = 0;
atg->prod_count = 0;
atg->size = 0;
atg->line_ending = "\n";
for (int i = 0; i < MAX_SECTIONS; i++) {
atg->characters[i] = NULL;
atg->tokens[i] = NULL;
atg->productions[i] = NULL;
}
return atg;
}
void ATGFile_destroy(ATGFile* atg) {
free(atg->filepath);
for (int i = 0; i < atg->char_count; i++) free(atg->characters[i]);
for (int i = 0; i < atg->token_count; i++) free(atg->tokens[i]);
for (int i = 0; i < atg->prod_count; i++) free(atg->productions[i]);
free(atg);
}
int ATGFile_read(ATGFile* atg) {
FILE* file = fopen(atg->filepath, "r");
if (!file) {
printf("Error: File %s not found.\n", atg->filepath);
return 1;
}
fseek(file, 0, SEEK_END);
atg->size = ftell(file);
fseek(file, 0, SEEK_SET);
char* content = (char*)malloc(atg->size + 1);
fread(content, 1, atg->size, file);
content[atg->size] = '\0';
fclose(file);
atg->line_ending = strstr(content, "\r\n") ? "\r\n" : "\n";
regex_t regex;
regcomp(®ex, "COMPILER[[:space:]]+([[:alnum:]]+)", REG_EXTENDED);
regmatch_t matches[2];
if (regexec(®ex, content, 2, matches, 0) == 0) {
atg->header = strndup(content + matches[1].rm_so, matches[1].rm_eo - matches[1].rm_so);
}
regfree(®ex);
regcomp(®ex, "CHARACTERS[[:space:]]+([[:alnum:]]+[[:space:]]*=[[:space:]]*[^.]+\\.)", REG_EXTENDED | REG_NEWLINE);
char* ptr = content;
while (regexec(®ex, ptr, 2, matches, 0) == 0 && atg->char_count < MAX_SECTIONS) {
atg->characters[atg->char_count++] = strndup(ptr + matches[1].rm_so, matches[1].rm_eo - matches[1].rm_so);
ptr += matches[0].rm_eo;
}
regfree(®ex);
regcomp(®ex, "TOKENS[[:space:]]+([[:alnum:]]+[[:space:]]*=[[:space:]]*[^.]+\\.)", REG_EXTENDED | REG_NEWLINE);
ptr = content;
while (regexec(®ex, ptr, 2, matches, 0) == 0 && atg->token_count < MAX_SECTIONS) {
atg->tokens[atg->token_count++] = strndup(ptr + matches[1].rm_so, matches[1].rm_eo - matches[1].rm_so);
ptr += matches[0].rm_eo;
}
regfree(®ex);
regcomp(®ex, "PRODUCTIONS[[:space:]]+([[:print:][:space:]]+?)END[[:space:]]+[[:alnum:]]+\\.", REG_EXTENDED);
if (regexec(®ex, content, 2, matches, 0) == 0) {
char* prod_str = strndup(content + matches[1].rm_so, matches[1].rm_eo - matches[1].rm_so);
char* line = strtok(prod_str, "\n");
while (line && atg->prod_count < MAX_SECTIONS) {
atg->productions[atg->prod_count++] = strdup(line);
line = strtok(NULL, "\n");
}
free(prod_str);
}
regfree(®ex);
free(content);
return 0;
}
int ATGFile_write(ATGFile* atg, const char* header, const char** characters, size_t char_count, const char** tokens, size_t token_count, const char** productions, size_t prod_count) {
FILE* file = fopen(atg->filepath, "w");
if (!file) {
printf("Error writing file: %s\n", atg->filepath);
return 1;
}
fprintf(file, "COMPILER %s%s", header, atg->line_ending);
fprintf(file, "CHARACTERS%s", atg->line_ending);
for (size_t i = 0; i < char_count; i++) {
fprintf(file, "%s%s", characters[i], atg->line_ending);
}
fprintf(file, "TOKENS%s", atg->line_ending);
for (size_t i = 0; i < token_count; i++) {
fprintf(file, "%s%s", tokens[i], atg->line_ending);
}
fprintf(file, "PRODUCTIONS%s", atg->line_ending);
for (size_t i = 0; i < prod_count; i++) {
fprintf(file, "%s%s", productions[i], atg->line_ending);
}
fprintf(file, "END %s.%s", header, atg->line_ending);
fclose(file);
atg->header = strdup(header);
for (size_t i = 0; i < atg->char_count; i++) free(atg->characters[i]);
for (size_t i = 0; i < atg->token_count; i++) free(atg->tokens[i]);
for (size_t i = 0; i < atg->prod_count; i++) free(atg->productions[i]);
atg->char_count = char_count;
atg->token_count = token_count;
atg->prod_count = prod_count;
for (size_t i = 0; i < char_count; i++) atg->characters[i] = strdup(characters[i]);
for (size_t i = 0; i < token_count; i++) atg->tokens[i] = strdup(tokens[i]);
for (size_t i = 0; i < prod_count; i++) atg->productions[i] = strdup(productions[i]);
file = fopen(atg->filepath, "r");
fseek(file, 0, SEEK_END);
atg->size = ftell(file);
fclose(file);
return 0;
}
void ATGFile_print_properties(ATGFile* atg) {
printf("extension: %s\n", atg->extension);
printf("file_type: %s\n", atg->file_type);
printf("encoding: %s\n", atg->encoding);
printf("header: %s\n", atg->header);
printf("characters: [");
for (size_t i = 0; i < atg->char_count; i++) {
printf("%s%s", atg->characters[i], i < atg->char_count - 1 ? ", " : "");
}
printf("]\n");
printf("tokens: [");
for (size_t i = 0; i < atg->token_count; i++) {
printf("%s%s", atg->tokens[i], i < atg->token_count - 1 ? ", " : "");
}
printf("]\n");
printf("productions: [");
for (size_t i = 0; i < atg->prod_count; i++) {
printf("%s%s", atg->productions[i], i < atg->prod_count - 1 ? ", " : "");
}
printf("]\n");
printf("size: %ld\n", atg->size);
printf("line_ending: %s\n", atg->line_ending);
}
int main() {
ATGFile* atg = ATGFile_create("example.atg");
ATGFile_read(atg);
ATGFile_print_properties(atg);
const char* chars[] = {"letter = 'a'..'z' + 'A'..'Z'"};
const char* tokens[] = {"ident = letter {letter | digit}"};
const char* prods[] = {"Start = ident ."};
ATGFile_write(atg, "ExampleGrammar", chars, 1, tokens, 1, prods, 1);
ATGFile_print_properties(atg);
ATGFile_destroy(atg);
return 0;
}
Notes and Assumptions
- File Format: The classes assume a Coco/R .ATG file structure with
COMPILER
,CHARACTERS
,TOKENS
,PRODUCTIONS
, andEND
sections, as no detailed specification was found. Parsing is simplified using regex to extract sections. - Error Handling: Each class includes basic error handling for file operations and parsing.
- Limitations: The regex-based parsing is basic and may not handle complex .ATG files. A full Coco/R parser would be needed for production use.
- Other Contexts: If the .ATG file is meant for Netmino, Oracle ATG, or another context, the structure would differ (e.g., Netmino might be binary, Oracle ATG is a Java properties file). Please specify the exact .ATG format for a more precise implementation.
- Sources: The properties and structure are inferred from Coco/R documentation and general text file characteristics, as no explicit .ATG specification was found in the provided references.
If you have a specific .ATG file or context (e.g., a sample file or application), I can refine the classes to match its structure. Let me know!
1. Properties of .ATG File Format (Coco/R Attributed Grammar)
- Structure: Text-based, EBNF syntax.
- Sections: Imports (optional), COMPILER declaration, global fields/methods (optional), scanner spec (IGNORECASE, CHARACTERS, TOKENS, PRAGMAS, COMMENTS, IGNORE), parser spec (PRODUCTIONS with name/attributes/local decl/expression), END declaration.
- Syntax elements: Identifiers (lower/upper case), strings, numbers, meta-characters (= . | () [] {}), attributes (< >), semantic actions ((. .)).
- Encoding: UTF-8 typical.
- Line endings: Platform-independent.
2. Python Class
import re
class ATGHandler:
def __init__(self, filepath):
self.filepath = filepath
self.content = ""
self.properties = {}
def read(self):
with open(self.filepath, 'r', encoding='utf-8') as f:
self.content = f.read()
self.parse()
def parse(self):
# Simple regex-based parsing for sections
self.properties['imports'] = re.findall(r'^(using|import|#include).*', self.content, re.M)
self.properties['compiler'] = re.search(r'COMPILER\s+(\w+)', self.content).group(1)
self.properties['end'] = re.search(r'END\s+(\w+)\.', self.content).group(1)
self.properties['scanner'] = {
'ignorecase': 'IGNORECASE' in self.content,
'characters': re.findall(r'CHARACTERS\s+(.*?)TOKENS', self.content, re.DOTALL),
'tokens': re.findall(r'TOKENS\s+(.*?)PRAGMAS|COMMENTS|IGNORE|PRODUCTIONS', self.content, re.DOTALL),
# Add similar for pragmas, comments, ignore
}
self.properties['parser'] = re.findall(r'PRODUCTIONS\s+(.*?)END', self.content, re.DOTALL)
# Full parsing would require EBNF parser; this is high-level
def write(self, new_properties):
# Reconstruct content from properties
self.content = f"COMPILER {new_properties['compiler']}\n"
# Add sections similarly
with open(self.filepath, 'w', encoding='utf-8') as f:
f.write(self.content)
3. Java Class
import java.io.*;
import java.util.regex.*;
public class ATGHandler {
private String filepath;
private String content;
private java.util.Map<String, Object> properties = new java.util.HashMap<>();
public ATGHandler(String filepath) {
this.filepath = filepath;
}
public void read() throws IOException {
BufferedReader br = new BufferedReader(new FileReader(filepath));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) sb.append(line).append("\n");
content = sb.toString();
br.close();
parse();
}
private void parse() {
// Similar regex parsing
Pattern p = Pattern.compile("COMPILER\\s+(\\w+)");
Matcher m = p.matcher(content);
if (m.find()) properties.put("compiler", m.group(1));
// Extend for other sections
}
public void write(java.util.Map<String, Object> newProperties) throws IOException {
// Reconstruct and write
String newContent = "COMPILER " + newProperties.get("compiler") + "\n";
BufferedWriter bw = new BufferedWriter(new FileWriter(filepath));
bw.write(newContent);
bw.close();
}
}
4. JavaScript Class
const fs = require('fs');
class ATGHandler {
constructor(filepath) {
this.filepath = filepath;
this.content = '';
this.properties = {};
}
read() {
this.content = fs.readFileSync(this.filepath, 'utf-8');
this.parse();
}
parse() {
this.properties.compiler = this.content.match(/COMPILER\s+(\w+)/)[1];
// Similar regex for sections
}
write(newProperties) {
let newContent = `COMPILER ${newProperties.compiler}\n`;
fs.writeFileSync(this.filepath, newContent, 'utf-8');
}
}
5. C Class
(Note: C uses structs/functions, not classes; emulated here.)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <regex.h> // For regex, may need POSIX regex
typedef struct {
char *filepath;
char *content;
// Use struct for properties
} ATGHandler;
ATGHandler* init_atg(char *filepath) {
ATGHandler *h = malloc(sizeof(ATGHandler));
h->filepath = strdup(filepath);
h->content = NULL;
return h;
}
void read_atg(ATGHandler *h) {
FILE *f = fopen(h->filepath, "r");
fseek(f, 0, SEEK_END);
long size = ftell(f);
fseek(f, 0, SEEK_SET);
h->content = malloc(size + 1);
fread(h->content, 1, size, f);
h->content[size] = '\0';
fclose(f);
// Parse with strstr or regex
}
void write_atg(ATGHandler *h, char *new_compiler) {
FILE *f = fopen(h->filepath, "w");
fprintf(f, "COMPILER %s\n", new_compiler);
fclose(f);
}
void free_atg(ATGHandler *h) {
free(h->content);
free(h->filepath);
free(h);
}