///|
fn get_lines(code : StringView) -> Array[StringView] {
code.split("\n").collect()
}
///|
struct CodePos {
line_no : Int
col_offset : Int
}
///|
fn get_code_pos(lines : Array[StringView], offset : @lib.Offset) -> CodePos {
let mut line_no = 0
let mut col_offset = offset
for line in lines {
line_no += 1
if col_offset < line.length() + 1 {
break CodePos::{ line_no, col_offset, }
}
col_offset -= line.length() + 1
} nobreak {
CodePos::{ line_no, col_offset: lines[line_no - 1].length(), }
}
}
///|
fn main raise {
let cmd = @argparse.Command(
"asdl-gen",
positionals=[
@argparse.PositionArg("filename", num_args=@argparse.ValueRange::single()),
],
options=[
@argparse.OptionArg("output", short='o', long="output"),
@argparse.OptionArg("target", long="target", default_values=["moonbit"]),
],
)
let args = cmd.parse().values
let filename = args["filename"][0]
let target = args["target"][0]
let source = @fs.read_file_to_string(filename) catch {
IOError(message) => abort("Failed to read \{filename}: \{message}")
}
let result = try {
match target {
"moonbit" => @lib.asdl_to_moonbit(source)
_ => abort("Unsupported target: \{target}")
}
} catch {
@lib.TokenizeError::UnknownSymbol(symbol) =>
abort("Unknown symbol '\{symbol}'")
@lib.ParseError::UnexpectedToken(token) => {
let lines = get_lines(source)
let { line_no, col_offset, } = get_code_pos(lines, token.pos)
let line = lines[line_no - 1]
println(
"\{filename}:\{line_no}:\{col_offset}: Unexpected token '\{Repr(token.body)}'",
)
println(line)
let token_length = match token.body {
@lib.TokenBody::TypeId(id) => id.length()
@lib.TokenBody::ConstructorId(id) => id.length()
_ => 1
}
let pointer_line = " ".repeat(col_offset) + "^".repeat(token_length)
println(pointer_line)
abort("Parse error at \{filename}:\{line_no}:\{col_offset}")
}
@lib.ParseError::UnexpectedEof =>
abort("Unexpected end of file while parsing \{filename}")
@lib.CheckError::TypeNotFound(type_id) =>
abort("Type '\{type_id}' not found in \{filename}")
@lib.CheckError::TypeRedefinition(type_id) =>
abort("Type '\{type_id}' redefined in \{filename}")
_ => abort("An unknown error occurred while processing \{filename}")
}
match args.get("output") {
Some([output]) => @fs.write_string_to_file(output, result)
_ => println(result)
}
}