Three lots of changes:

1) Changes post code review by Jason
2) Fixing bug in end of line processing on Windows with cr-lf
3) Adding command-line options to chai
This commit is contained in:
clanmills 2011-02-16 08:21:19 -08:00
parent 894063261e
commit 65d054b36e
3 changed files with 156 additions and 123 deletions

View File

@ -492,7 +492,7 @@ namespace chaiscript
* Helper function for loading a file * Helper function for loading a file
*/ */
std::string load_file(const std::string &t_filename) { std::string load_file(const std::string &t_filename) {
std::ifstream infile(t_filename.c_str(), std::ios::in | std::ios::ate); std::ifstream infile(t_filename.c_str(), std::ios::in | std::ios::ate | std::ios::binary );
if (!infile.is_open()) { if (!infile.is_open()) {
throw File_Not_Found_Error(t_filename); throw File_Not_Found_Error(t_filename);

View File

@ -7,7 +7,6 @@
#ifndef CHAISCRIPT_PARSER_HPP_ #ifndef CHAISCRIPT_PARSER_HPP_
#define CHAISCRIPT_PARSER_HPP_ #define CHAISCRIPT_PARSER_HPP_
#include <exception> #include <exception>
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
@ -15,9 +14,6 @@
#include "chaiscript_prelude.hpp" #include "chaiscript_prelude.hpp"
#include "chaiscript_common.hpp" #include "chaiscript_common.hpp"
#define lengthof(x) (((int)sizeof(x))/((int)sizeof(x[0])))
namespace chaiscript namespace chaiscript
{ {
enum Alphabet enum Alphabet
@ -32,6 +28,7 @@ namespace chaiscript
, id_alphabet , id_alphabet
, white_alphabet , white_alphabet
, max_alphabet , max_alphabet
, lengthof_alphabet = 256
}; };
class ChaiScript_Parser { class ChaiScript_Parser {
@ -43,7 +40,7 @@ namespace chaiscript
std::string m_singleline_comment; std::string m_singleline_comment;
boost::shared_ptr<std::string> m_filename; boost::shared_ptr<std::string> m_filename;
std::vector<AST_NodePtr> m_match_stack; std::vector<AST_NodePtr> m_match_stack;
bool alphabet[max_alphabet][256]; bool alphabet[max_alphabet][lengthof_alphabet];
std::vector<std::vector<std::string> > m_operator_matches; std::vector<std::vector<std::string> > m_operator_matches;
std::vector<AST_Node_Type::Type> m_operators; std::vector<AST_Node_Type::Type> m_operators;
@ -126,7 +123,7 @@ namespace chaiscript
m_operator_matches.push_back(dot_access); m_operator_matches.push_back(dot_access);
int c; int c;
for ( c = 0 ; c < lengthof(alphabet[0]) ; c++ ) { for ( c = 0 ; c < lengthof_alphabet ; c++ ) {
for ( int a = 0 ; a < max_alphabet ; a ++ ) { for ( int a = 0 ; a < max_alphabet ; a ++ ) {
alphabet[a][c]=false; alphabet[a][c]=false;
} }
@ -251,19 +248,6 @@ namespace chaiscript
} }
} }
/**
* Does ranged char check
*/
/*
inline bool char_between(char t_start, char t_end) {
if ((*m_input_pos >= t_start) && (*m_input_pos <= t_end)) {
return true;
}
else {
return false;
}
}
*/
/** /**
* Check to see if there is more text parse * Check to see if there is more text parse
*/ */
@ -315,7 +299,7 @@ namespace chaiscript
bool SkipWS() { bool SkipWS() {
bool retval = false; bool retval = false;
while (has_more_input()) { while (has_more_input()) {
if ( char_in_alphabet(*m_input_pos,white_alphabet) ) { // (*m_input_pos == ' ') || (*m_input_pos == '\t')) { if ( char_in_alphabet(*m_input_pos,white_alphabet) ) {
++m_input_pos; ++m_input_pos;
++m_col; ++m_col;
retval = true; retval = true;
@ -337,17 +321,17 @@ namespace chaiscript
bool retval = false; bool retval = false;
std::string::const_iterator start = m_input_pos; std::string::const_iterator start = m_input_pos;
if (has_more_input() && char_in_alphabet(*m_input_pos,float_alphabet) ) { // (char_between('0', '9') || (*m_input_pos == '.'))) { if (has_more_input() && char_in_alphabet(*m_input_pos,float_alphabet) ) {
while (has_more_input() && char_in_alphabet(*m_input_pos,int_alphabet) ) { // char_between('0', '9')) { while (has_more_input() && char_in_alphabet(*m_input_pos,int_alphabet) ) {
++m_input_pos; ++m_input_pos;
++m_col; ++m_col;
} }
if (has_more_input() && (*m_input_pos == '.')) { if (has_more_input() && (*m_input_pos == '.')) {
++m_input_pos; ++m_input_pos;
++m_col; ++m_col;
if (has_more_input() && char_in_alphabet(*m_input_pos,int_alphabet)) { // char_between('0', '9')) { if (has_more_input() && char_in_alphabet(*m_input_pos,int_alphabet)) {
retval = true; retval = true;
while (has_more_input() && char_in_alphabet(*m_input_pos,int_alphabet) ) { //char_between('0', '9')) { while (has_more_input() && char_in_alphabet(*m_input_pos,int_alphabet) ) {
++m_input_pos; ++m_input_pos;
++m_col; ++m_col;
} }
@ -370,16 +354,12 @@ namespace chaiscript
++m_input_pos; ++m_input_pos;
++m_col; ++m_col;
if (has_more_input() && char_in_alphabet(*m_input_pos,x_alphabet) ) { // ((*m_input_pos == 'x') || (*m_input_pos == 'X'))) { if (has_more_input() && char_in_alphabet(*m_input_pos,x_alphabet) ) {
++m_input_pos; ++m_input_pos;
++m_col; ++m_col;
if (has_more_input() && char_in_alphabet(*m_input_pos,hex_alphabet)) { // (char_between('0', '9') || if (has_more_input() && char_in_alphabet(*m_input_pos,hex_alphabet)) {
// char_between('a', 'f') ||
// char_between('A', 'F'))) {
retval = true; retval = true;
while (has_more_input() && char_in_alphabet(*m_input_pos,hex_alphabet) ) { // (char_between('0', '9') || while (has_more_input() && char_in_alphabet(*m_input_pos,hex_alphabet) ) {
// char_between('a', 'f') ||
// char_between('A', 'F'))) {
++m_input_pos; ++m_input_pos;
++m_col; ++m_col;
} }
@ -407,12 +387,12 @@ namespace chaiscript
++m_input_pos; ++m_input_pos;
++m_col; ++m_col;
if (has_more_input() && char_in_alphabet(*m_input_pos,b_alphabet) ) { // ((*m_input_pos == 'b') || (*m_input_pos == 'B'))) { if (has_more_input() && char_in_alphabet(*m_input_pos,b_alphabet) ) {
++m_input_pos; ++m_input_pos;
++m_col; ++m_col;
if (has_more_input() && char_in_alphabet(*m_input_pos,bin_alphabet) ) { // char_between('0', '1')) { if (has_more_input() && char_in_alphabet(*m_input_pos,bin_alphabet) ) {
retval = true; retval = true;
while (has_more_input() && char_in_alphabet(*m_input_pos,bin_alphabet) ) { // char_between('0', '1')) { while (has_more_input() && char_in_alphabet(*m_input_pos,bin_alphabet) ) {
++m_input_pos; ++m_input_pos;
++m_col; ++m_col;
} }
@ -444,7 +424,7 @@ namespace chaiscript
std::string::const_iterator start = m_input_pos; std::string::const_iterator start = m_input_pos;
int prev_col = m_col; int prev_col = m_col;
int prev_line = m_line; int prev_line = m_line;
if (has_more_input() && char_in_alphabet(*m_input_pos,float_alphabet) ) { // (char_between('0', '9') || (*m_input_pos == '.')) ) { if (has_more_input() && char_in_alphabet(*m_input_pos,float_alphabet) ) {
if (Hex_()) { if (Hex_()) {
std::string match(start, m_input_pos); std::string match(start, m_input_pos);
std::stringstream ss(match); std::stringstream ss(match);
@ -512,11 +492,9 @@ namespace chaiscript
*/ */
bool Id_() { bool Id_() {
bool retval = false; bool retval = false;
if (has_more_input() && char_in_alphabet(*m_input_pos,id_alphabet)) { // (char_between('A', 'Z') || (*m_input_pos == '_') || char_between('a', 'z'))) { if (has_more_input() && char_in_alphabet(*m_input_pos,id_alphabet)) {
retval = true; retval = true;
while (has_more_input() && char_in_alphabet(*m_input_pos,keyword_alphabet) ) { while (has_more_input() && char_in_alphabet(*m_input_pos,keyword_alphabet) ) {
// (char_between('A', 'Z') || (*m_input_pos == '_') ||
// char_between('a', 'z') || char_between('0', '9'))) {
++m_input_pos; ++m_input_pos;
++m_col; ++m_col;
} }
@ -1972,6 +1950,7 @@ namespace chaiscript
while ((m_input_pos != m_input_end) && (!Eol())) { while ((m_input_pos != m_input_end) && (!Eol())) {
++m_input_pos; ++m_input_pos;
} }
// TODO: respect // -*- coding: utf-8 -*- on line 1 or 2 see: http://evanjones.ca/python-utf8.html)
} }
if (Statements()) { if (Statements()) {

View File

@ -24,14 +24,27 @@ static void add_history(const char*){}
static void using_history(){} static void using_history(){}
#endif #endif
void print_help() { static void help(int n) {
if ( n >= 0 ) {
std::cout << "ChaiScript evaluator. To evaluate an expression, type it and press <enter>." << std::endl; std::cout << "ChaiScript evaluator. To evaluate an expression, type it and press <enter>." << std::endl;
std::cout << "Additionally, you can inspect the runtime system using:" << std::endl; std::cout << "Additionally, you can inspect the runtime system using:" << std::endl;
std::cout << " dump_system() - outputs all functions registered to the system" << std::endl; std::cout << " dump_system() - outputs all functions registered to the system" << std::endl;
std::cout << " dump_object(x) - dumps information about the given symbol" << std::endl; std::cout << " dump_object(x) - dumps information about the given symbol" << std::endl;
} else {
std::cout << "usage: chai [option]+" << std::endl;
std::cout << " -h | --help" << std::endl;
std::cout << " -i | --interactive" << std::endl;
std::cout << " -c | --command cmd" << std::endl;
std::cout << " -v | --version" << std::endl;
std::cout << " - --stdin" << std::endl;
}
} }
bool throws_exception(const chaiscript::Proxy_Function &f) static void version(int){
std::cout << "chai: compiled " << __TIME__ << " " << __DATE__ << std::endl;
}
static bool throws_exception(const chaiscript::Proxy_Function &f)
{ {
try { try {
chaiscript::functor<void ()>(f)(); chaiscript::functor<void ()>(f)();
@ -42,34 +55,41 @@ bool throws_exception(const chaiscript::Proxy_Function &f)
return false; return false;
} }
std::string get_next_command() { static std::string trim(std::string source,const std::string& t)
{
std::string result = source ;
result.erase(result.find_last_not_of(t)+1);
result.erase(0, result.find_first_not_of(t));
return result ;
}
static std::string get_next_command() {
std::string retval("quit"); std::string retval("quit");
if ( ! std::cin.eof() ) { if ( ! std::cin.eof() ) {
char *input_raw = readline("eval> "); char *input_raw = readline("eval> ");
if ( input_raw ) { if ( input_raw ) {
add_history(input_raw); add_history(input_raw);
retval = input_raw; retval = trim(std::string(input_raw),std::string(" \t"));
::free(input_raw); ::free(input_raw);
if ( retval == "help" ) {
print_help();
retval="";
}
if ( retval == "quit" || retval == "exit" ) {
retval="exit(0)";
} }
} }
if(retval == "quit"
|| retval == "exit"
|| retval == "help"
|| retval == "version"
){
retval += "(0)";
} }
return retval; return retval;
} }
// We have to wrap exit with our own because Clang has a hard time with // We have to wrap exit with our own because Clang has a hard time with
// function pointers to functions with special attributes (system exit being marked NORETURN) // function pointers to functions with special attributes (system exit being marked NORETURN)
void myexit(int return_val) { static void myexit(int return_val) {
std::cout << "thanks for using ChaiScript" << std::endl ;
exit(return_val); exit(return_val);
} }
void interactive(chaiscript::ChaiScript& chai) static void interactive(chaiscript::ChaiScript& chai)
{ {
using_history(); using_history();
@ -103,8 +123,6 @@ void interactive(chaiscript::ChaiScript& chai)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
int error = EXIT_SUCCESS;
std::vector<std::string> usepaths; std::vector<std::string> usepaths;
std::vector<std::string> modulepaths; std::vector<std::string> modulepaths;
@ -136,14 +154,52 @@ int main(int argc, char *argv[])
chaiscript::ChaiScript chai(modulepaths,usepaths); chaiscript::ChaiScript chai(modulepaths,usepaths);
chai.add(chaiscript::fun(&myexit), "exit"); chai.add(chaiscript::fun(&myexit), "exit");
chai.add(chaiscript::fun(&myexit), "quit");
chai.add(chaiscript::fun(&help), "help");
chai.add(chaiscript::fun(&version), "version");
chai.add(chaiscript::fun(&throws_exception), "throws_exception"); chai.add(chaiscript::fun(&throws_exception), "throws_exception");
if (argc < 2) { for (int i = 0; i < argc; ++i) {
interactive(chai); if ( i == 0 && argc > 1 ) i++ ;
std::string arg( i ? argv[i] : "--interactive" );
enum
{ eInteractive
, eCommand
, eFile
} mode = eCommand ;
if ( arg == "-c" || arg == "--command" ) {
if ( (i+1) >= argc ) {
std::cout << "insufficient input following " << arg << std::endl;
return EXIT_FAILURE;
} else { } else {
for (int i = 1; !error && (i < argc); ++i) { arg = argv[++i];
}
} else if ( arg == "-" || arg == "--stdin" ) {
arg = "" ;
std::string line;
while ( std::getline(std::cin, line) ) {
arg += line ;
}
} else if ( arg == "-v" || arg == "--version" ) {
arg = "version(0)" ;
} else if ( arg == "-h" || arg == "--help" ) {
arg = "help(-1)";
} else if ( arg == "-i" || arg == "--interactive" ) {
mode = eInteractive ;
} else if ( (arg.length() ? arg[0] : ' ') == '-' ) {
std::cout << "unrecognised argument " << arg << std::endl;
return EXIT_FAILURE;
} else {
mode = eFile;
}
chaiscript::Boxed_Value val ;
try { try {
chaiscript::Boxed_Value val = chai.eval_file(argv[i]); switch ( mode ) {
case eInteractive : interactive(chai); break;
case eCommand : val = chai.eval(arg); break;
case eFile : val = chai.eval_file(arg); break;
}
} }
catch (chaiscript::Eval_Error &ee) { catch (chaiscript::Eval_Error &ee) {
std::cout << ee.what(); std::cout << ee.what();
@ -155,15 +211,13 @@ int main(int argc, char *argv[])
} }
} }
std::cout << std::endl; std::cout << std::endl;
error = EXIT_FAILURE; return EXIT_FAILURE;
} }
catch (std::exception &e) { catch (std::exception &e) {
std::cout << e.what() << std::endl; std::cout << e.what() << std::endl;
error = EXIT_FAILURE; return EXIT_FAILURE;
}
} }
} }
return error ; return EXIT_SUCCESS;
} }