mirror of
https://github.com/Gers2017/cpp.js.git
synced 2024-11-25 08:18:41 -06:00
feat(command line arguments): Add --target and --help flags
- Move generate_rust_code to interpreter - Clean stuff.js - Parse command line arguments
This commit is contained in:
parent
9898335592
commit
9a1ad1e7a4
24
interpreter.js
Normal file
24
interpreter.js
Normal 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
92
main.js
|
@ -1,6 +1,7 @@
|
||||||
import { readFileSync, writeFileSync } from "fs";
|
import { readFileSync } from "fs";
|
||||||
import { Parser } from "./parser.js";
|
import { Parser } from "./parser.js";
|
||||||
import { PrintStmt, ReturnStmt } from "./stuff.js";
|
import { generate_rust_code } from "./interpreter.js";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
is_alpha,
|
is_alpha,
|
||||||
is_alphanum,
|
is_alphanum,
|
||||||
|
@ -8,6 +9,7 @@ import {
|
||||||
is_whitespace,
|
is_whitespace,
|
||||||
pretty_error,
|
pretty_error,
|
||||||
panic,
|
panic,
|
||||||
|
exit_rand,
|
||||||
} from "./utils.js";
|
} from "./utils.js";
|
||||||
|
|
||||||
// Javascript enums at home
|
// Javascript enums at home
|
||||||
|
@ -287,46 +289,96 @@ class Lexer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const TARGETS = [
|
||||||
|
"rust",
|
||||||
|
"x86_64-fasm-linux-gnu",
|
||||||
|
// "x86_64-fasm-windows"
|
||||||
|
];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
_main();
|
_main();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(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() {
|
function _main() {
|
||||||
const CPP_REGEX = /.\.cpp/i;
|
const CPP_REGEX = /.\.cpp/i;
|
||||||
const args = process.argv;
|
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)) {
|
if (CPP_REGEX.test(arg)) {
|
||||||
filename = 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 source = readFileSync(filename, "utf8");
|
||||||
const lexer = new Lexer(source);
|
const lexer = new Lexer(source);
|
||||||
const tokens = lexer.scan_tokens();
|
const tokens = lexer.scan_tokens();
|
||||||
|
|
||||||
// console.log(lexer.tokens);
|
|
||||||
|
|
||||||
const parser = new Parser(tokens);
|
const parser = new Parser(tokens);
|
||||||
const statements = parser.parse();
|
const statements = parser.parse();
|
||||||
|
|
||||||
const output = [];
|
switch (target) {
|
||||||
output.push("fn main() {");
|
case TARGETS[0]: // rust
|
||||||
|
filename = filename.replace(".cpp", ".rs");
|
||||||
|
generate_rust_code(filename, statements);
|
||||||
|
break;
|
||||||
|
|
||||||
for (const stmt of statements) {
|
case TARGETS[1]: // x86_64-fasm-linux-gnu
|
||||||
if (stmt instanceof PrintStmt) {
|
filename = filename.replace(".cpp", ".asm");
|
||||||
output.push(`\tprint!("${stmt.string}");`);
|
// TODO GENERATE ASM!
|
||||||
} else if (stmt instanceof ReturnStmt) {
|
default:
|
||||||
output.push(`\tstd::process::exit(${stmt.value});`);
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
output.push("}\n");
|
|
||||||
const text = output.join("\n");
|
|
||||||
|
|
||||||
filename = filename.replace("cpp", "rs");
|
|
||||||
writeFileSync(filename, text);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// ------- Parser --------
|
// ------- Parser --------
|
||||||
|
|
||||||
import { Token, TokenType } from "./main.js";
|
import { Token, TokenType } from "./main.js";
|
||||||
import { PrintStmt, ReturnStmt } from "./stuff.js";
|
import { PrintStmt, ReturnStmt, Stmt } from "./stuff.js";
|
||||||
import { panic } from "./utils.js";
|
import { panic } from "./utils.js";
|
||||||
|
|
||||||
const Errors = {
|
const Errors = {
|
||||||
|
|
27
stuff.js
27
stuff.js
|
@ -1,13 +1,5 @@
|
||||||
export class AST {}
|
|
||||||
export class Stmt {}
|
export class Stmt {}
|
||||||
|
|
||||||
export class Block extends AST {
|
|
||||||
constructor(stmts) {
|
|
||||||
super();
|
|
||||||
this.stmts = stmts;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class PrintStmt extends Stmt {
|
export class PrintStmt extends Stmt {
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -37,23 +29,26 @@ export class IfStmt extends Stmt {}
|
||||||
|
|
||||||
export class ElseStmt extends Stmt {}
|
export class ElseStmt extends Stmt {}
|
||||||
|
|
||||||
export class Expr {}
|
export class AST {}
|
||||||
|
|
||||||
export class EqualsExpr {
|
export class Block extends AST {
|
||||||
constructor(a, b) {
|
constructor(stmts) {
|
||||||
this.a = a;
|
super();
|
||||||
this.b = b;
|
this.stmts = stmts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Num {
|
export class NumberNode extends AST {
|
||||||
constructor(value) {
|
constructor(value) {
|
||||||
|
super();
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class FunctionDeclaration extends Stmt {
|
export class BinaryExpr extends AST {
|
||||||
constructor(name, params, body) {
|
constructor(left, right) {
|
||||||
super();
|
super();
|
||||||
|
this.left = left;
|
||||||
|
this.right = right;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue