Add support for escape sequences in character symbols

This commit is contained in:
Matthias Schiffer 2015-04-10 19:00:43 +02:00
parent 475326bf12
commit aeaeba2d73
5 changed files with 103 additions and 23 deletions

View file

@ -337,13 +337,67 @@ int lex_t::lex(parse_token_value_t *value) {
if (!next(true)) if (!next(true))
return syntax_error(value); return syntax_error(value);
value->c = current(); if (current() == '\\') {
if (!next(true))
return syntax_error(value);
switch (current()) {
case 'a':
value->c = '\a';
break;
case 'b':
value->c = '\b';
break;
case 'f':
value->c = '\f';
break;
case 'n':
value->c = '\n';
break;
case 'r':
value->c = '\r';
break;
case 't':
value->c = '\t';
break;
case 'v':
value->c = '\v';
break;
case '\\':
value->c = '\\';
break;
case '\'':
value->c = '\'';
break;
case '"':
value->c = '"';
break;
case '?':
value->c = '?';
break;
default:
return syntax_error(value);
}
}
else {
value->c = current();
}
if (!next(true) || current() != '\'') if (!next(true) || current() != '\'')
return syntax_error(value); return syntax_error(value);
next(true); next(true);
consume(false); consume(false);
return TOK_CHAR; return TOK_CHAR;
@ -354,9 +408,6 @@ int lex_t::lex(parse_token_value_t *value) {
case '"': case '"':
return lex_string(value); return lex_string(value);
//case '0' ... '9':
//return lex_number(value);
case 'a' ... 'z': case 'a' ... 'z':
case 'A' ... 'Z': case 'A' ... 'Z':
return lex_symbol(value); return lex_symbol(value);

View file

@ -64,6 +64,48 @@ void output_t::initialize() {
} }
} }
std::string output_t::symbol_case(const symbol_t &sym) {
if (sym.get_type() == SYMBOL_TYPE_CHAR) {
switch (sym.get_value()[0]) {
case '\a':
return "'\\a'";
case '\b':
return "'\\b'";
case '\f':
return "'\\f'";
case '\n':
return "'\\n'";
case '\r':
return "'\\r'";
case '\t':
return "'\\t'";
case '\v':
return "'\\v'";
case '\\':
return "'\\\\'";
case '\'':
return "'\\''";
default:
return "'" + sym.get_value() + "'";
}
}
else {
if (sym.get_value().empty())
return "0";
else
return token_prefix_str + sym.get_value();
}
}
void output_t::emit_tokens() { void output_t::emit_tokens() {
if (tokens.empty()) if (tokens.empty())
return; return;

View file

@ -57,6 +57,8 @@ protected:
return token_prefix_str.c_str(); return token_prefix_str.c_str();
} }
std::string symbol_case(const symbol_t &sym);
void emit_tokens(); void emit_tokens();
void emit_token_value(); void emit_token_value();
void emit_header(); void emit_header();

View file

@ -42,11 +42,7 @@ void output_lr0_t::emit_state_shift(unsigned i) {
if (it == generator->get_shifts().end()) if (it == generator->get_shifts().end())
continue; continue;
if (token.get_type() == SYMBOL_TYPE_CHAR) std::fprintf(source_file, "\t\t\tcase %s:\n", symbol_case(token).c_str());
std::fprintf(source_file, "\t\t\tcase '%c':\n", token.get_value()[0]);
else
std::fprintf(source_file, "\t\t\tcase %s%s:\n", token_prefix(), token.get_value().c_str());
std::fprintf(source_file, "\t\t\t\tparser->stack[parser->top].value.token = *value;\n"); std::fprintf(source_file, "\t\t\t\tparser->stack[parser->top].value.token = *value;\n");
std::fprintf(source_file, "\t\t\t\tparser->stack[++parser->top].state = %u;\n", unsigned(it->second)); std::fprintf(source_file, "\t\t\t\tparser->stack[++parser->top].state = %u;\n", unsigned(it->second));
std::fprintf(source_file, "\t\t\t\treturn 1;\n\n"); std::fprintf(source_file, "\t\t\t\treturn 1;\n\n");

View file

@ -38,25 +38,14 @@ void output_slr_t::emit_state_shift(unsigned i, const symbol_t &token) {
if (it == generator->get_shifts().end()) if (it == generator->get_shifts().end())
return; return;
if (token.get_type() == SYMBOL_TYPE_CHAR) std::fprintf(source_file, "\t\t\tcase %s:\n", symbol_case(token).c_str());
std::fprintf(source_file, "\t\t\tcase '%c':\n", token.get_value()[0]);
else if (!token.get_value().empty())
std::fprintf(source_file, "\t\t\tcase %s%s:\n", token_prefix(), token.get_value().c_str());
else
std::fprintf(source_file, "\t\t\tcase 0:\n");
std::fprintf(source_file, "\t\t\t\tparser->stack[parser->top].value.token = *value;\n"); std::fprintf(source_file, "\t\t\t\tparser->stack[parser->top].value.token = *value;\n");
std::fprintf(source_file, "\t\t\t\tparser->stack[++parser->top].state = %u;\n", unsigned(it->second)); std::fprintf(source_file, "\t\t\t\tparser->stack[++parser->top].state = %u;\n", unsigned(it->second));
std::fprintf(source_file, "\t\t\t\treturn 1;\n\n"); std::fprintf(source_file, "\t\t\t\treturn 1;\n\n");
} }
void output_slr_t::emit_state_reduce(const item_t &item, const symbol_t &token, int rule_id) { void output_slr_t::emit_state_reduce(const item_t &item, const symbol_t &token, int rule_id) {
if (token.get_type() == SYMBOL_TYPE_CHAR) std::fprintf(source_file, "\t\t\tcase %s:\n", symbol_case(token).c_str());
std::fprintf(source_file, "\t\t\tcase '%c':\n", token.get_value()[0]);
else if (!token.get_value().empty())
std::fprintf(source_file, "\t\t\tcase %s%s:\n", token_prefix(), token.get_value().c_str());
else
std::fprintf(source_file, "\t\t\tcase 0:\n");
const auto &rhs = item.get_rhs(); const auto &rhs = item.get_rhs();
if (rhs.size()) if (rhs.size())