HTMLify

tokens.c
Views: 2 | Author: abh
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "tokens.h"

Variable *Variables = NULL;
int Variables_count = 0;

// Variable functions

Variable *Variable_init(char *name, VarType type) {
    static Variable var;
    var.type = type;
    if (name != NULL) {
        strcpy(var.name, name);
        Variables = realloc(Variables, ++Variables_count*sizeof(Variable));
        Variables[Variables_count-1] = var;
    } else {
        var.name[0] = '\0';
    }
    return &var;
}

void Variable_assign(Variable *var, VarValue value) {
    switch (var->type) {
        case character:
            var->value._char = value._char;
            break;
        case integer:
            var->value._int = value._int;
            break;
        case floating:
            var->value._float = value._float;
            break;
        case string:
            var->value._str = value._str;
            break;
        case none:
            break;
    }
}

void Variable_repr(Variable *var, char *str) {
    switch (var->type) {
        case character:
            sprintf(str, "%c", var->value._char);
            break;
        case integer:
            sprintf(str, "%d", var->value._int);
            break;
        case floating:
            sprintf(str, "%.2f", var->value._float);
            break;
        case string:
            sprintf(str, "%s", var->value._str);
            break;
        case none:
            // sprintf(str, "");
            break;
    }
}

Variable Variable_op(Variable *this, Operator op, const Variable *that) {
    Variable result = *Variable_init(NULL, this->type);
    switch (op) {
        case ASN:
            Variable_assign(this, that->value);
            return *this;
        case ADD:
            switch (this->type) {
                case character:
                    result.value._char = this->value._char + that->value._char;
                    break;
                case integer:
                    result.value._int = this->value._int + that->value._int;
                    break;
                case floating:
                    result.value._float = this->value._float + that->value._float;
                    break;
            }
            break;
        case SUB:
            switch (this->type) {
                case character:
                    result.value._char = this->value._char + that->value._char;
                    break;
                case integer:
                    result.value._int = this->value._int + that->value._int;
                    break;
                case floating:
                    result.value._float = this->value._float + that->value._float;
                    break;
            }
            break;
        case DIV:
            switch (this->type) {
                case integer:
                    result.value._int = this->value._int / that->value._int;
                    break;
                case floating:
                    result.value._float = this->value._float / that->value._float;
            }
            break;
        case MUL:
            switch (this->type) {
                case integer:
                    result.value._int = this->value._int * that->value._int;
                    break;
                case floating:
                    result.value._float = this->value._float * that->value._float;
            }
            break;
    }
    return result;
}

Variable *Get_variable(char *name, bool named) {
    for (int i = 0; i<Variables_count; i++) {
        if (strcmp(Variables[i].name, name) == 0)
            return &Variables[i];
    }
    static Variable *var;
    if (named)
        return Variable_init(name, none);
    return Variable_init(NULL, none);
}

void Del_variable(char *name) {
    bool found = false;
    if (Variables_count == 0)
        return;
    if (strcmp(Variables[Variables_count-1].name, name)==0) {
        Variables_count--;
        return;
    }
    for (int i = 0; i<Variables_count-1; i++) {
        if (strcmp(Variables[i].name, name) == 0)
            found = true;
        if (found)
            Variables[i] = Variables[i+1];
    }
    if (found)
        Variables_count--;
}

bool Exist_variable(char *name) {
    for (int i=0; i<Variables_count; i++)
        if (strcmp(Variables[i].name, name) == 0)
            return true;
    return false;
}

VarValue Literal_value(const char *name, VarType type) {
    VarValue value;
    int len = strlen(name);
    switch (type) {
        case character:
            if (len > 2) {
                value._char = name[1];
            } else {
                value._char = '\0';
            }
            break;
        case integer:
            // if (len == 0) {
            //     value._int = 0;
            // } else {
            //     value._int = atoi(name);
            // }
            sscanf(name, "%d", &value._int);
            break;
        case floating:
            // if (len == 0) {
            //     value._float = 0.0;
            // } else {
            //     value._float = atof(name);
                sscanf(name, "%f", &value._float);
            // }
            break;
        case string:
            strcpy(value._str, name);
            value._str[len-1] = '\0';
            value._str = &value._str[1];
            break;
        case none:
            break;
    }
    return value;
}


// Token functions

TokenType Token_type(const char *name) {
    int i, len = strlen(name);

    // Operators
    if (len == 1) {
        if (strcmp(name, "=") == 0) 
            return OPERATOR;
        if (strcmp(name, "+") == 0) 
            return OPERATOR;
        if (strcmp(name, "-") == 0) 
            return OPERATOR;
        if (strcmp(name, "/") == 0) 
            return OPERATOR;
        if (strcmp(name, "*") == 0) 
            return OPERATOR;
    }

    // Keywords
    char _kws_[][16] = {
        "DEF", "def",
        "INT", "int",
        "FLOAT", "float",
        "CHAR", "char",
        "STR", "str",
        "DEL", "del",
        "PRINT", "print",
        "TYPE", "type"
    };
    for (i=0; i<17; i++)
        if (strcmp(name, _kws_[i]) == 0)
            return KEYWORD;

    // Literals

    bool is_int = true;
    for (i=0; i<len; i++)
        if (name[i] < 48 || 57 < name[i]) 
            is_int = false;
    if (is_int)
        return LITERAL;

    bool is_float = true;
    for (i=0; i<len; i++)
        if (name[i] < 48 || 57 < name[i] || name[i] != '.')
            is_float = false;
    if (is_float)
        return LITERAL;

    bool is_char = false;
    char _tbec_[5] = { '\'', '\"', '\\', '\n', '\r' };
    if ((len == 3 || len == 4)) {
        if (name[0] == '\'' && name[len-1] == '\'') {
            if (len == 3) {
                bool ve = true;
                for (i=0; i<5; i++)
                    if (_tbec_[i] == name[1])
                        ve = false;
                if (ve) 
                    is_char = true;
            }
            if (len == 4) {
                if (name[1] == '\\') {
                    for (i=0; i<6; i++)
                        if (_tbec_[i] == name[2])
                            is_char = true;
                }
            }
        }
    }
    if (is_char)
        return LITERAL;

    bool is_str = false;
    /* char _tbec_[5] */
    if (name[0] == '\"' && name[len-1] == '\"') {
        int si = 0;
        bool es_before = false;
        char ch;
        for (si=1; si<len-1; si++) {
            es_before = false;
            ch = name[si];
            if (ch == '\\') {
                es_before = true;
                continue;
            }
            if (es_before) {
                bool ve = false;
                for (i=0; i<5; i++)
                    if (_tbec_[i] == ch)
                        ve = true;
                if (!ve)
                    break;
            }
        }
        if (!es_before)
            is_str = true;
    }

    bool is_variable = true;
    char _ainc_[63] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
    for (i=0; i<len; i++) {
        char ch = name[i];
        if (i == 0 && 48 <= ch && ch <= 57)
            is_variable = false;
        if (ch == '.')
            is_variable = false;
        bool vch = false;
        int j;
        for (j=0; j<63; j++)
            if (_ainc_[j] == ch)
                vch = true;
        if (!vch)
            is_variable = false;
    }
    if (is_variable)
        return VARIABLE;

    return NONE;
}

Keyword Get_keyword(const char *name) {
    if (strcmp(name, "def") == 0 || strcmp(name, "DEF") == 0)
        return DEF;
    if (strcmp(name, "int") == 0 || strcmp(name, "INT") == 0)
        return INT;
    if (strcmp(name, "float") == 0 || strcmp(name, "FLOAT") == 0)
        return FLOAT;
    if (strcmp(name, "char") == 0 || strcmp(name, "CHAR") == 0)
        return CHAR;
    if (strcmp(name, "str") == 0 || strcmp(name, "STR") == 0)
        return STR;
    if (strcmp(name, "del") == 0 || strcmp(name, "DEL") == 0)
        return DEL;
    if (strcmp(name, "print") == 0 || strcmp(name, "PRINT") == 0)
        return PRINT; 
    if (strcmp(name, "type") == 0 || strcmp(name, "TYPE") == 0)
        return TYPE;
};

Operator Get_operator(const char *name) {
    if (name[0] == '=')
        return ASN;
    if (name[0] == '+')
        return ADD;
    if (name[0] == '-')
        return SUB;
    if (name[0] == '/')
        return DIV;
    if (name[0] == '*')
        return MUL;
};

char *Type_token(Token token) {
    switch (token.type) {
        case OPERATOR:
            switch (token.value.operator) {
                case ASN:
                    return "Assign Operator";
                case ADD:
                    return "Addition Operator";
                case SUB:
                    return "Substraction Operator";
                case DIV:
                    return "Division Operator";
                case MUL:
                    return "Multipication Operator";
            }
            break;
        case KEYWORD:
            switch (token.value.keyword) {
                case DEF:
                    return "Keyword: Define";
                case INT:
                    return "Int cast keyword";
                case CHAR:
                    return "Char cast keyword";
                case FLOAT:
                    return "Float cast keyword";
                case STR:
                    return "String cast keyword";
                case DEL:
                    return "Keyword: Delete";
                case PRINT:
                    return "Print Keyword";
                case TYPE:
                    return "Type Keyword";
            }
        case VARIABLE:
            switch (token.value.variable->type) {
                case character:
                    return "Character Type Variable";
                case integer:
                    return "Integer Type Variable";
                case floating:
                    return "Floating point Type Variable";
                case string:
                    return "Stling Type Variable";
                case none:
                    return "None Type Variable";
            }
        case LITERAL:
            return "Literal";
        case NONE:
            return "NONE";
    }
}

Comments