~kameliya/kyuubey

b24d9d60ed895ed041b6ee7ffb0f3bf5b5a1be68 — Yuki Izumi 6 years ago 5c186f2
Binary operators, imm
4 files changed, 116 insertions(+), 8 deletions(-)

M lang.l
M lang.y
M parser.c
M parser.h
M lang.l => lang.l +4 -1
@@ 1,11 1,14 @@
%{
    #include <stdlib.h>

    #include "parser.h"
    #include "lang.tab.h"
%}

%%

\"[^"\n]+\"?    { yylval.expr = ast_string_alloc(yytext + 1); return EXPR; }
\"[^"\n]+\"?    { yylval.expr = ast_string_alloc(yytext + 1); return IMM; }
[0-9]+             { yylval.expr = ast_integer_alloc(atoi(yytext)); return IMM; }
REM[^\n]+       { yylval.comment = ast_comment_alloc(yytext + 3, 1); return COMMENT; }
'[^\n]+         { yylval.comment = ast_comment_alloc(yytext + 1, 0); return COMMENT; }
[a-zA-Z]+       { yylval.token = ast_token_alloc(yytext); return TOKEN; }

M lang.y => lang.y +19 -6
@@ 18,11 18,16 @@
%token NL

%token <token> TOKEN
%token <expr> EXPR
%token <expr> IMM
%token <comment> COMMENT

%type <stmt> line stmt
%type <expr> exprlist opt_exprlist
%type <expr> expr exprlist opt_exprlist

%left '+' '-'
%left '*' '/'

%left '(' ')'

%%



@@ 43,14 48,22 @@ stmt:           TOKEN opt_exprlist      { $$ = ast_stmt_alloc(STMT_CALL); $$->ca
              | COMMENT                 { $$ = ast_stmt_alloc(STMT_COMMENT); $$->comment = $1; }
;

exprlist:       EXPR                    { $$ = $1; }
              | EXPR ',' exprlist       { $$ = $1; $1->next = $3; $1->nexttype = ','; }
              | EXPR ';' exprlist       { $$ = $1; $1->next = $3; $1->nexttype = ';'; }
              | EXPR exprlist           { $$ = $1; $1->next = $2; $1->nexttype = ';'; }
exprlist:       expr                    { $$ = $1; }
              | expr ',' exprlist       { $$ = $1; $1->next = $3; $1->nexttype = ','; }
              | expr ';' exprlist       { $$ = $1; $1->next = $3; $1->nexttype = ';'; }
              | expr exprlist           { $$ = $1; $1->next = $2; $1->nexttype = ';'; }
;

opt_exprlist:   /* empty */             { $$ = 0; }
              | exprlist                { $$ = $1; }
;

expr:           IMM                     { $$ = $1; }
              | '(' expr ')'            { $$ = $2; }
              | expr '+' expr           { $$ = ast_binary_alloc('+', $1, $3); }
              | expr '-' expr           { $$ = ast_binary_alloc('-', $1, $3); }
              | expr '*' expr           { $$ = ast_binary_alloc('*', $1, $3); }
              | expr '/' expr           { $$ = ast_binary_alloc('/', $1, $3); }
;

/* vim: set sw=4 et: */

M parser.c => parser.c +81 -1
@@ 20,12 20,44 @@ ast_expr_t *ast_string_alloc(char const *value) {
    return expr;
}

ast_expr_t *ast_binary_alloc(char op, ast_expr_t *a, ast_expr_t *b) {
    ast_expr_t *expr = malloc(sizeof(*expr));
    memset(expr, 0, sizeof(*expr));
    expr->type = EXPR_BINARY;
    expr->binary.op = op;
    expr->binary.a = a;
    expr->binary.b = b;

    return expr;
}

ast_expr_t *ast_integer_alloc(int i) {
    ast_expr_t *expr = malloc(sizeof(*expr));
    memset(expr, 0, sizeof(*expr));
    expr->type = EXPR_INTEGER;
    expr->integer = i;

    return expr;
}

void ast_expr_pp(ast_expr_t *expr) {
    switch (expr->type) {
    case EXPR_STRING:
        printf("\"%s\"", expr->string);
        break;

    case EXPR_BINARY:
        printf("(");
        ast_expr_pp(expr->binary.a);
        printf(" %c ", expr->binary.op);
        ast_expr_pp(expr->binary.b);
        printf(")");
        break;

    case EXPR_INTEGER:
        printf("%d", expr->integer);
        break;

    default:
        fprintf(stderr, "UNKNOWN EXPR TYPE %d\n", expr->type);
    }


@@ 37,12 69,29 @@ void ast_expr_free(ast_expr_t *expr) {
        free(expr->string);
        break;

    default:
    case EXPR_BINARY:
        ast_expr_free(expr->binary.a);
        ast_expr_free(expr->binary.b);
        break;

    case EXPR_INTEGER:
        /* empty */
        break;

    default:
        fprintf(stderr, "UNKNOWN EXPR TYPE %d\n", expr->type);
    }
    free(expr);
}

void ast_expr_free_list(ast_expr_t *expr) {
    while (expr) {
        ast_expr_t *next = expr->next;
        ast_expr_free(expr);
        expr = next;
    }
}

/* ast_comment_t */

ast_comment_t *ast_comment_alloc(char const *value, int is_rem) {


@@ 110,9 159,31 @@ void ast_stmt_pp(ast_stmt_t *stmt) {
}

void ast_stmt_free(ast_stmt_t *stmt) {
    switch (stmt->type) {
    case STMT_CALL:
        ast_token_free(stmt->call.target);
        ast_expr_free_list(stmt->call.args);
        break;

    case STMT_COMMENT:
        ast_comment_free(stmt->comment);
        break;

    default:
        fprintf(stderr, "UNKNOWN STMT TYPE %d\n", stmt->type);
        break;
    }
    free(stmt);
}

void ast_stmt_free_list(ast_stmt_t *stmt) {
    while (stmt) {
        ast_stmt_t *next = stmt->next;
        ast_stmt_free(stmt);
        stmt = next;
    }
}

/* ast_t */

ast_t *ast_alloc(void) {


@@ 138,6 209,7 @@ void ast_pp(ast_t *ast) {
}

void ast_free(ast_t *ast) {
    ast_stmt_free_list(ast->stmts);
    free(ast);
}



@@ 156,6 228,14 @@ int parser_test(void) {

    begin_scan(
        "PRINT \"Hello\"; \"there\", \"pals\" \"!\"\n"
        "REM 1 + 2 * 3\n"
        "PRINT 1 + 2 * 3\n"
        "REM (1 + 2) * 3\n"
        "PRINT (1 + 2) * 3\n"
        "REM 1 * 2 + 3\n"
        "PRINT 1 * 2 + 3\n"
        "REM 1 * (2 + 3)\n"
        "PRINT 1 * (2 + 3)\n"
        "GOTO\n"
        "\n"
        "REM Okay, sure thing.\n"

M parser.h => parser.h +12 -0
@@ 5,6 5,8 @@

typedef enum {
    EXPR_STRING,
    EXPR_BINARY,
    EXPR_INTEGER,
} ast_expr_type_t;

typedef struct ast_expr {


@@ 12,6 14,12 @@ typedef struct ast_expr {

    union {
        char *string;
        struct {
            char op;
            struct ast_expr *a;
            struct ast_expr *b;
        } binary;
        int integer;
    };

    struct ast_expr *next;


@@ 19,8 27,11 @@ typedef struct ast_expr {
} ast_expr_t;

ast_expr_t *ast_string_alloc(char const *value);
ast_expr_t *ast_binary_alloc(char op, ast_expr_t *a, ast_expr_t *b);
ast_expr_t *ast_integer_alloc(int i);
void ast_expr_pp(ast_expr_t *expr);
void ast_expr_free(ast_expr_t *expr);
void ast_expr_free_list(ast_expr_t *expr);

/* ast_comment_t */



@@ 65,6 76,7 @@ typedef struct ast_stmt {
ast_stmt_t *ast_stmt_alloc(ast_stmt_type_t type);
void ast_stmt_pp(ast_stmt_t *stmt);
void ast_stmt_free(ast_stmt_t *stmt);
void ast_stmt_free_list(ast_stmt_t *stmt);

/* ast_t */