feat(command line arguments): Add --target and --help flags

- Move generate_rust_code to interpreter
- Clean stuff.js
- Parse command line arguments
main
Gers2017 2023-05-04 16:23:08 -06:00
parent 9898335592
commit 9a1ad1e7a4
4 changed files with 108 additions and 37 deletions

24
interpreter.js Normal file
View File

@ -0,0 +1,24 @@
import { writeFileSync } from "fs";
import { Stmt, PrintStmt, ReturnStmt } from "./stuff.js";
/**
*
* @param {Stmt[]} statements
*/
export function generate_rust_code(filename, statements) {
const output = [];
output.push("fn main() {");
for (const stmt of statements) {
if (stmt instanceof PrintStmt) {
output.push(`\tprint!("${stmt.string}");`);
} else if (stmt instanceof ReturnStmt) {
output.push(`\tstd::process::exit(${stmt.value});`);
}
}
output.push("}\n");
const text = output.join("\n");
writeFileSync(filename, text);
}

92
main.js
View File

@ -1,6 +1,7 @@
import { readFileSync, writeFileSync } from "fs";
import { readFileSync } from "fs";
import { Parser } from "./parser.js";
import { PrintStmt, ReturnStmt } from "./stuff.js";
import { generate_rust_code } from "./interpreter.js";
import {
is_alpha,
is_alphanum,
@ -8,6 +9,7 @@ import {
is_whitespace,
pretty_error,
panic,
exit_rand,
} from "./utils.js";
// Javascript enums at home
@ -287,46 +289,96 @@ class Lexer {
}
}
const TARGETS = [
"rust",
"x86_64-fasm-linux-gnu",
// "x86_64-fasm-windows"
];
try {
_main();
} catch (e) {
console.error(e);
}
function check_next_arg(arg, next_arg) {
if (next_arg === null && !next_arg.startsWith("-")) {
console.error(`Missing or invalid value for flag "${arg}"`);
exit_rand();
}
return true;
}
function print_usage() {
console.log("Cpp.js");
console.log("USAGE:");
console.log(" node cpp.js <filename>");
console.log(" node cpp.js <filename> --target <target>");
console.log(" node cpp.js --target list");
console.log(" node cpp.js --help");
console.log();
console.log(" <filename>: The cpp file to compile");
console.log(" <target>: The target platform");
}
function _main() {
const CPP_REGEX = /.\.cpp/i;
const args = process.argv;
let filename = "main.cpp";
for (const arg of args) {
let filename = "main.cpp";
let target = TARGETS[0]; // default target is rust
for (let i = 0; i < args.length; i++) {
const arg = args[i];
const next_arg = i + 1 < args.length ? args[i + 1] : null;
if (arg === "--help") {
print_usage();
process.exit(0);
}
if (CPP_REGEX.test(arg)) {
filename = arg;
}
if (arg === "--target" && check_next_arg(arg, next_arg)) {
if (next_arg === "list") {
console.log("Valid targets:");
for (const target of TARGETS) {
console.log(target);
}
process.exit(0);
}
if (!TARGETS.includes(next_arg)) {
console.error(
`Unknown target "${next_arg}\nMaybe try: --target list`
);
exit_rand();
}
target = next_arg;
}
}
const source = readFileSync(filename, "utf8");
const lexer = new Lexer(source);
const tokens = lexer.scan_tokens();
// console.log(lexer.tokens);
const parser = new Parser(tokens);
const statements = parser.parse();
const output = [];
output.push("fn main() {");
switch (target) {
case TARGETS[0]: // rust
filename = filename.replace(".cpp", ".rs");
generate_rust_code(filename, statements);
break;
for (const stmt of statements) {
if (stmt instanceof PrintStmt) {
output.push(`\tprint!("${stmt.string}");`);
} else if (stmt instanceof ReturnStmt) {
output.push(`\tstd::process::exit(${stmt.value});`);
}
case TARGETS[1]: // x86_64-fasm-linux-gnu
filename = filename.replace(".cpp", ".asm");
// TODO GENERATE ASM!
default:
break;
}
output.push("}\n");
const text = output.join("\n");
filename = filename.replace("cpp", "rs");
writeFileSync(filename, text);
}

View File

@ -1,7 +1,7 @@
// ------- Parser --------
import { Token, TokenType } from "./main.js";
import { PrintStmt, ReturnStmt } from "./stuff.js";
import { PrintStmt, ReturnStmt, Stmt } from "./stuff.js";
import { panic } from "./utils.js";
const Errors = {

View File

@ -1,13 +1,5 @@
export class AST {}
export class Stmt {}
export class Block extends AST {
constructor(stmts) {
super();
this.stmts = stmts;
}
}
export class PrintStmt extends Stmt {
/**
*
@ -37,23 +29,26 @@ export class IfStmt extends Stmt {}
export class ElseStmt extends Stmt {}
export class Expr {}
export class AST {}
export class EqualsExpr {
constructor(a, b) {
this.a = a;
this.b = b;
export class Block extends AST {
constructor(stmts) {
super();
this.stmts = stmts;
}
}
export class Num {
export class NumberNode extends AST {
constructor(value) {
super();
this.value = value;
}
}
export class FunctionDeclaration extends Stmt {
constructor(name, params, body) {
export class BinaryExpr extends AST {
constructor(left, right) {
super();
this.left = left;
this.right = right;
}
}