コード例 #1
0
ファイル: Reader.cpp プロジェクト: kanaka/mal
static malValuePtr readForm(Tokeniser& tokeniser)
{
    MAL_CHECK(!tokeniser.eof(), "expected form, got EOF");
    String token = tokeniser.peek();

    MAL_CHECK(!std::regex_match(token, closeRegex),
            "unexpected '%s'", token.c_str());

    if (token == "(") {
        tokeniser.next();
        std::unique_ptr<malValueVec> items(new malValueVec);
        readList(tokeniser, items.get(), ")");
        return mal::list(items.release());
    }
    if (token == "[") {
        tokeniser.next();
        std::unique_ptr<malValueVec> items(new malValueVec);
        readList(tokeniser, items.get(), "]");
        return mal::vector(items.release());
    }
    if (token == "{") {
        tokeniser.next();
        malValueVec items;
        readList(tokeniser, &items, "}");
        return mal::hash(items.begin(), items.end(), false);
    }
    return readAtom(tokeniser);
}
コード例 #2
0
ファイル: compiler.cpp プロジェクト: bagedevimo/petlang
int main(int argc, char** argv) {
	Tokeniser* intok;
	Parser* parser;

	ifstream* fin;
	bool verbose = false;
	string output;
	string infile;

	// @neo how does this shit work?

	int c, prev_ind;
	while((c = getopt(argc, argv, "vo:")) != EOF)
	{
		switch (c) {
           	case 'v':
            	verbose = true;
            	break;
            case 'o':
            	output = optarg;
            	break;
            default:
            	cout << "unknown argument: " << char(c) << endl;
            	break;
        }
    }

    if(optind < argc) infile = argv[optind];
    fin = new ifstream(infile);

	if(infile.length() == 0) {
		intok = new Tokeniser(&cin);
	} else {
		intok = new Tokeniser(fin);
	}

	ofstream* out = nullptr;
	if(output.length() > 0) out = new ofstream(output);

	queue<token> tokenstream;
	
	token t;
	do {
		t = intok->next();
		tokenstream.push(t);
		
		if(verbose) cout << t << endl;

		if(out) *out << t.type << endl << t.str << endl;

	} while (t.type != token::eof);

	if(out) delete out;

	parser = new Parser();
	queue<symbol*>* symbol_s = parser->create_symbol_stream(tokenstream);
	parser->do_parse(symbol_s);
		
	return 0;
}
コード例 #3
0
ファイル: Reader.cpp プロジェクト: kanaka/mal
static void readList(Tokeniser& tokeniser, malValueVec* items,
                      const String& end)
{
    while (1) {
        MAL_CHECK(!tokeniser.eof(), "expected '%s', got EOF", end.c_str());
        if (tokeniser.peek() == end) {
            tokeniser.next();
            return;
        }
        items->push_back(readForm(tokeniser));
    }
}
コード例 #4
0
ファイル: Reader.cpp プロジェクト: kanaka/mal
static malValuePtr readAtom(Tokeniser& tokeniser)
{
    struct ReaderMacro {
        const char* token;
        const char* symbol;
    };
    ReaderMacro macroTable[] = {
        { "@",   "deref" },
        { "`",   "quasiquote" },
        { "'",   "quote" },
        { "~@",  "splice-unquote" },
        { "~",   "unquote" },
    };

    struct Constant {
        const char* token;
        malValuePtr value;
    };
    Constant constantTable[] = {
        { "false",  mal::falseValue()  },
        { "nil",    mal::nilValue()          },
        { "true",   mal::trueValue()   },
    };

    String token = tokeniser.next();
    if (token[0] == '"') {
        return mal::string(unescape(token));
    }
    if (token[0] == ':') {
        return mal::keyword(token);
    }
    if (token == "^") {
        malValuePtr meta = readForm(tokeniser);
        malValuePtr value = readForm(tokeniser);
        // Note that meta and value switch places
        return mal::list(mal::symbol("with-meta"), value, meta);
    }
    for (auto &constant : constantTable) {
        if (token == constant.token) {
            return constant.value;
        }
    }
    for (auto &macro : macroTable) {
        if (token == macro.token) {
            return processMacro(tokeniser, macro.symbol);
        }
    }
    if (std::regex_match(token, intRegex)) {
        return mal::integer(token);
    }
    return mal::symbol(token);
}