/* Utility Functions
*****************************************************************************/
typedef enum {
+ TOKFILE,
+ ASTFILE,
CSOURCE,
OBJECT,
PROGRAM,
str_t* get_extension(file_type_t ftype) {
str_t* ext = NULL;
switch (ftype) {
+ case TOKFILE: ext = str_new(".tok"); break;
+ case ASTFILE: ext = str_new(".ast"); break;
case CSOURCE: ext = str_new(".c"); break;
case OBJECT: ext = str_new(".o"); break;
case PROGRAM: ext = str_new(""); break;
}
vec_t* parse_file(str_t* in) {
+ bool failed = false;
FILE* input = (NULL == in) ? stdin : fopen(str_cstr(in), "r");
parser_t* p_parser = parser_new(NULL, input);
vec_t* p_vec = vec_new(0);
- bool failed = false;
while(!parser_eof(p_parser)) {
tree_t* p_tree = grammar_toplevel(p_parser);
if (NULL != p_tree) {
return ((failed) ? NULL : p_vec);
}
+vec_t* program_deps(vec_t* program) {
+ vec_t* deps = vec_new(0);
+ (void)program;
+ return deps;
+}
+
+str_t* token_file(str_t* in) {
+ str_t* ofname = NULL;
+ FILE* input = (NULL == in) ? stdin : fopen(str_cstr(in), "r");
+ FILE* output;
+ if (NULL == in) {
+ output = stdout;
+ } else {
+ ofname = get_filename(TOKFILE, in);
+ output = fopen(str_cstr(ofname), "w");
+ }
+
+ lexer_t* p_lexer = lexer_new(NULL, input);
+ lex_tok_t* token;
+ while(NULL != (token = lexer_read(p_lexer))) {
+ pprint_token(output, token);
+ mem_release(token);
+ }
+ mem_release(p_lexer);
+
+ return ofname;
+}
+
+str_t* syntax_file(str_t* in) {
+ str_t* ofname = NULL;
+ FILE* output;
+ if (NULL == in) {
+ output = stdout;
+ } else {
+ ofname = get_filename(ASTFILE, in);
+ output = fopen(str_cstr(ofname), "w");
+ }
+ vec_t* program = parse_file(in);
+ if (NULL != program) {
+ for (size_t idx = 0; idx < vec_size(program); idx++) {
+ pprint_tree(output, (tree_t*)vec_at(program, idx), 0);
+ }
+ mem_release(program);
+ fclose(output);
+ } else {
+ fclose(output);
+ remove(str_cstr(ofname));
+ mem_release(ofname);
+ ofname = NULL;
+ }
+ return ofname;
+}
+
str_t* translate_file(str_t* in) {
str_t* ofname = NULL;
FILE* output;
/* Driver Modes
*****************************************************************************/
static int emit_tokens(void) {
- lexer_t* p_lexer = lexer_new(NULL, stdin);
- lex_tok_t* token;
- while(NULL != (token = lexer_read(p_lexer))) {
- pprint_token(stdout, token);
- mem_release(token);
+ list_t* files = input_files();
+ size_t nfiles = list_size(files);
+ if (0 == nfiles) {
+ (void)token_file(NULL);
+ } else if (1 == nfiles) {
+ str_t* fname = list_front(files)->contents;
+ mem_release( token_file(fname) );
+ } else {
+ error_msg("too many files provided for target mode 'tokens'");
}
- mem_release(p_lexer);
+ mem_release(files);
return 0;
}
static int emit_tree(void) {
int ret = 0;
- parser_t* p_parser = parser_new(NULL, stdin);
- while(!parser_eof(p_parser)) {
- tree_t* p_tree = grammar_toplevel(p_parser);
- if (NULL != p_tree) {
- tree_t* p_ast = convert_to_ast(p_tree);
- pprint_tree(stdout, p_ast, 0);
- mem_release(p_tree);
- mem_release(p_ast);
- } else {
- parser_resume(p_parser);
- ret = 1;
- }
+ list_t* files = input_files();
+ size_t nfiles = list_size(files);
+ if (0 == nfiles) {
+ (void)syntax_file(NULL);
+ } else if (1 == nfiles) {
+ str_t* fname = list_front(files)->contents;
+ mem_release( syntax_file(fname) );
+ } else {
+ error_msg("too many files provided for target mode 'ast'");
}
- mem_release(p_parser);
+ mem_release(files);
+
return ret;
}
void pprint_token_value(FILE* file, lex_tok_t* token) {
void* value = token->value;
switch(token->type) {
- case T_STRING: fprintf(file, "\"%s\"", ((char*)value)); break;
- case T_CHAR: print_char(file, ((char)(int)value)); break;
- case T_INT: fprintf(file, "%ld", *((long int*)value)); break;
- case T_FLOAT: fprintf(file, "%f", *((double*)value)); break;
- case T_BOOL: fprintf(file, "%s", ((int)value)?"true":"false"); break;
- case T_VAR: fprintf(file, "%s", ((char*)value)); break;
- default: fprintf(file, "???"); break;
+ case T_STRING: fprintf(file, "\"%s\"", ((char*)value)); break;
+ case T_CHAR: print_char(file, ((char)(intptr_t)value)); break;
+ case T_INT: fprintf(file, "%ld", *((long int*)value)); break;
+ case T_FLOAT: fprintf(file, "%f", *((double*)value)); break;
+ case T_BOOL: fprintf(file, "%s", ((intptr_t)value)?"true":"false"); break;
+ case T_VAR: fprintf(file, "%s", ((char*)value)); break;
+ default: fprintf(file, "???"); break;
}
}
if (tree->tag == ATOM) {
pprint_token(file, tree->ptr.tok);
} else {
- puts("(tree");
+ fputs("(tree", file);
vec_t* p_vec = tree->ptr.vec;
for(size_t idx = 0; idx < vec_size(p_vec); idx++) {
pprint_tree(file, (tree_t*)vec_at(p_vec, idx), depth+1);
}
print_indent(file, depth);
- puts(")");
+ fputs(")\n", file);
}
}
--- /dev/null
+require 'spec_helper'
+
+describe "cli" do
+ context "token mode" do
+ it "should accept input from stdin" do
+ expect(cli(['--tokens'])).to eq("")
+ end
+
+ it "should translate the input file" do
+ expect(cli(['--tokens', 'spec/src/sample.scl'])).to eq("")
+ expect(File.exists? 'spec/src/sample.tok').to be(true)
+ FileUtils.rm('spec/src/sample.tok')
+ end
+ end
+
+ context "ast mode" do
+ it "should accept input from stdin" do
+ expect(cli(['--ast'])).to eq("")
+ end
+
+ it "should translate the input file" do
+ expect(cli(['--ast', 'spec/src/sample.scl'])).to eq("")
+ expect(File.exists? 'spec/src/sample.ast').to be(true)
+ FileUtils.rm('spec/src/sample.ast')
+ end
+ end
+
+ context "c source mode" do
+ it "should accept input from stdin" do
+ expect(cli(['--csource'])).not_to eq("")
+ end
+
+ it "should translate the input file" do
+ expect(cli(['--csource', 'spec/src/sample.scl'])).to eq("")
+ expect(File.exists? 'spec/src/sample.c').to be(true)
+ FileUtils.rm('spec/src/sample.c')
+ end
+ end
+
+ context "object mode" do
+ it "should error when too few input files provided" do
+ expect{cli(['--object'])}.to raise_error(/too few files/)
+ end
+
+ it "should error when too many input files provided" do
+ expect{cli(['--object', 'spec/src/sample.scl', 'spec/src/sample.scl'])}.to raise_error(/too many files/)
+ end
+
+ it "should compile the input file in verbose mode (short flag)" do
+ pending "Can't find the sclpl header"
+ expect(cli(['-v', '--object', 'spec/src/sample.scl'])).to eq(
+ "clang -c -o spec/src/sample.o spec/src/sample.c")
+ expect(File.exists? 'spec/src/sample.o').to be(true)
+ FileUtils.rm('spec/src/sample.o')
+ end
+
+ it "should compile the input file in verbose mode (long flag)" do
+ pending "Can't find the sclpl header"
+ expect(cli(['--verbose', '--object', 'spec/src/sample.scl'])).to eq(
+ "clang -c -o spec/src/sample.o spec/src/sample.c")
+ expect(File.exists? 'spec/src/sample.o').to be(true)
+ FileUtils.rm('spec/src/sample.o')
+ end
+
+ it "should compile the input file" do
+ pending "Can't find the sclpl header"
+ expect(cli(['--object', 'spec/src/sample.scl'])).to eq("")
+ expect(File.exists? 'spec/src/sample.o').to be(true)
+ FileUtils.rm('spec/src/sample.o')
+ end
+ end
+end
+
require 'open3'
-def lexer(input)
- out, err, status = Open3.capture3('./build/bin/sclpl-test', '--tokens', :stdin_data => input)
- raise "Lexer command returned non-zero status" unless status.success?
+def cli(options, input = "")
+ out, err, status = Open3.capture3(
+ *(['./build/bin/sclpl-test'] + options + [{:stdin_data => input}]))
raise err unless err == ""
- out.scan(/^(T_[A-Z]+(:("[^"]*"|[^\n]+))?)/m).map {|m| m[0] }
+ raise "Command returned non-zero status" unless status.success?
+ out
+end
+
+def lexer(input)
+ cli(['--tokens'], input).scan(/^(T_[A-Z]+(:("[^"]*"|[^\n]+))?)/m).map {|m| m[0] }
end
def re_structure( token_array, offset = 0 )
end
def ast(input)
- out, err, status = Open3.capture3('./build/bin/sclpl-test', '--ast', :stdin_data => input)
- raise err unless err == ""
- raise "Parser command returned non-zero status" unless status.success?
+ out = cli(['--ast'], input)
# Prep the parens for reading
out.gsub!(/([()])|tree/,' \1 ')
# Replace string literals so we can tokenize on spaces
end
def ccode(input)
- out, err, status = Open3.capture3('./build/bin/sclpl-test', '--csource', :stdin_data => input)
- raise err unless err == ""
- raise "Parser command returned non-zero status" unless status.success?
- out
+ cli(['--csource'], input)
end