summaryrefslogblamecommitdiff
path: root/src/sexpr/main.cpp
blob: 7d63ddfe9690b6971de751e29418116633ab1ced (plain) (tree)

































































































































                                                                              
#include <stack>
#include <map>

#include "../io/cxxstdio.hpp"

#include "lexer.hpp"
#include "parser.hpp"

#include "../poison.hpp"

enum Spacing
{
    LINES,
    SIMPLE,
    SPACES,
    SPACES_1,
    SPACES_2,
    SPACES_3,
    SPACES_4,
};

static
void do_spacing(bool& first, Spacing& sp, int depth)
{
    if (first)
    {
        first = false;
        return;
    }
    switch (sp)
    {
    case LINES:
        PRINTF("\n%*s", (depth - 1) * 4, "");
        return;
    case SPACES:
    case SIMPLE:
        PRINTF(" ");
        return;
    case SPACES_1:
        PRINTF(" ");
        sp = LINES;
        return;
    case SPACES_2:
        PRINTF(" ");
        sp = SPACES_1;
        return;
    case SPACES_3:
        PRINTF(" ");
        sp = SPACES_2;
        return;
    case SPACES_4:
        PRINTF(" ");
        sp = SPACES_3;
        return;
    }
}

static
void adjust_spacing(Spacing& sp, ZString val)
{
    std::map<ZString, Spacing> spaces =
    {
        {"BLOCK", LINES},
        {"GUARD", LINES},
        {"DISABLED", LINES},
        {"PROCEDURE", SPACES_2},
        {"SPELL", SPACES_4},
        {"IF", SPACES_1},
        {"set_script_variable", SPACES_2},
    };
    auto it = spaces.find(val);
    if (it != spaces.end())
        sp = it->second;
}

int main()
{
    if (1 == 1)
    {
        sexpr::Lexer lexer("/dev/stdin");
        sexpr::SExpr sexpr;
        while (sexpr::parse(lexer, sexpr))
        {
            PRINTF("");
        }
        if (lexer.peek() != sexpr::TOK_EOF)
        {
            lexer.span().error(STRPRINTF("Incomplete: %s: %s\n",
                        sexpr::token_name(lexer.peek()), lexer.val_string()));
        }
        return 0;
    }

    std::stack<Spacing> spacing;
    spacing.push(LINES);
    sexpr::Lexer lexer("/dev/stdin");
    bool first = true;
    while (sexpr::Lexeme tok = lexer.peek())
    {
        switch (tok)
        {
        case sexpr::TOK_OPEN:
            if (spacing.top() == SIMPLE)
                spacing.top() = LINES;
            do_spacing(first, spacing.top(), spacing.size());
            PRINTF("(");
            spacing.push(SIMPLE);
            first = true;
            break;
        case sexpr::TOK_CLOSE:
            PRINTF(")");
            spacing.pop();
            first = false;
            break;
        case sexpr::TOK_STRING:
            do_spacing(first, spacing.top(), spacing.size());
            PRINTF("%s", sexpr::escape(lexer.val_string()));
            break;
        case sexpr::TOK_TOKEN:
            do_spacing(first, spacing.top(), spacing.size());
            PRINTF("%s", lexer.val_string());
            adjust_spacing(spacing.top(), lexer.val_string());
            break;
        default:
            abort();
        }
        lexer.adv();
    }
    PRINTF("\n");
}