~kameliya/kyuubey

e7cbf3567b334ce30dbbe3de27d418f1b2a487ca — Yuki Izumi 6 years ago 5c4d459
pp, add comments for pp sake
5 files changed, 165 insertions(+), 12 deletions(-)

M Makefile
M lang.l
M lang.y
M parser.c
M parser.h
M Makefile => Makefile +1 -1
@@ 1,7 1,7 @@
BIN = ./kyuubey
BUILD_DIR = out

CFLAGS = -I. -Iout $(shell $(SDL2_CONFIG) --cflags) -Wall -g
CFLAGS = -I. -Iout $(shell $(SDL2_CONFIG) --cflags) -g -Wall -Wno-unneeded-internal-declaration -Wno-unused-function
LDFLAGS = $(shell $(SDL2_CONFIG) --libs) -lSDL2main

SDL2_CONFIG = /usr/local/bin/sdl2-config

M lang.l => lang.l +6 -1
@@ 1,4 1,5 @@
%{
    #include "parser.h"
    #include "lang.tab.h"
%}



@@ 13,7 14,11 @@

%%

[a-zA-Z]        { return TOKEN; }
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; }
[\t ]+          { }
.               { return yytext[0]; }
\n              { return NL; }

%%

M lang.y => lang.y +18 -3
@@ 5,13 5,26 @@
%parse-param {ast_t *ast}
%error-verbose

%token TOKEN NL
%union {
    ast_comment_t *comment;
    ast_token_t *token;

    ast_stmt_t *stmt;
}

%token END_OF_FILE 0 "$end"

%token NL

%token <token> TOKEN
%token <comment> COMMENT

%type <stmt> line stmt

%%

input:          /* empty */
              | input line { if ($2) { ast_append(ast, $2); } }
              | input line { if ($2) { ast_append_stmt(ast, $2); } }
;

line_separator: NL


@@ 23,6 36,8 @@ line:           line_separator          { $$ = 0; }
              | stmt END_OF_FILE        { $$ = $1; }
;

stmt: ;
stmt:           TOKEN                   { $$ = ast_stmt_alloc(STMT_CALL); $$->call.target = $1; }
              | COMMENT                 { $$ = ast_stmt_alloc(STMT_COMMENT); $$->comment = $1; }
;

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

M parser.c => parser.c +87 -3
@@ 1,35 1,119 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "parser.h"

/* ast_comment_t */

ast_comment_t *ast_comment_alloc(char const *value, int is_rem) {
    ast_comment_t *comment = malloc(sizeof(*comment));
    memset(comment, 0, sizeof(*comment));
    comment->value = strdup(value);
    comment->is_rem = is_rem;
    return comment;
}

void ast_comment_free(ast_comment_t *comment) {
    free(comment->value);
    free(comment);
}

/* ast_token_t */

ast_token_t *ast_token_alloc(char const *value) {
    ast_token_t *token = malloc(sizeof(*token));
    memset(token, 0, sizeof(*token));
    token->value = strdup(value);
    return token;
}

void ast_token_free(ast_token_t *token) {
    free(token->value);
    free(token);
}

/* ast_stmt_t */

ast_stmt_t *ast_stmt_alloc(ast_stmt_type_t type) {
    ast_stmt_t *stmt = malloc(sizeof(*stmt));
    memset(stmt, 0, sizeof(*stmt));
    stmt->type = type;
    return stmt;
}

void ast_stmt_pp(ast_stmt_t *stmt) {
    switch (stmt->type) {
    case STMT_CALL:
        printf("%s\n", stmt->call.target->value);
        break;

    case STMT_COMMENT:
        printf("%s%s\n", stmt->comment->is_rem ? "REM" : "'", stmt->comment->value);
        break;

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

void ast_stmt_free(ast_stmt_t *stmt) {
    free(stmt);
}

/* ast_t */

ast_t *ast_alloc(void) {
    ast_t *ast = malloc(sizeof(*ast));
    memset(ast, 0, sizeof(*ast));
    return ast;
}

void ast_append(ast_t *ast, void *x) {
void ast_append_stmt(ast_t *ast, ast_stmt_t *stmt) {
    ast_stmt_t **writer = &ast->stmts;
    while (*writer) {
        writer = &(*writer)->next;
    }
    *writer = stmt;
}

void ast_pp(ast_t *ast) {
    ast_stmt_t *stmt = ast->stmts;
    while (stmt) {
        ast_stmt_pp(stmt);
        stmt = stmt->next;
    }
}

void ast_free(ast_t *ast) {
    free(ast);
}

/* flex/bison */

int yywrap(void) {
    return 1;
}

void yyerror(ast_t *ast, char const *s) {
    fprintf(stderr, "boop: %s\n", s);
    fprintf(stderr, "parse error: %s\n", s);
}

int parser_test(void) {
    ast_t *ast = ast_alloc();

    begin_scan("PRINT \"HELLO\"");
    begin_scan(
        "PRINT\n"
        "GOTO\n"
        "\n"
        "REM Okay, sure thing.\n"
        "'I guess.\n");
    yyparse(ast);
    finish_scan();

    ast_pp(ast);

    free(ast);

    return 0;

M parser.h => parser.h +53 -4
@@ 1,18 1,67 @@
#ifndef PARSER_H
#define PARSER_H

/* ast_comment_t */

typedef struct {
    char *value;
    int is_rem;
} ast_comment_t;

} ast_t;
ast_comment_t *ast_comment_alloc(char const *value, int is_rem);
void ast_comment_free(ast_comment_t *comment);

int yylex(void);
int yyparse(ast_t *ast);
/* ast_token_t */

typedef struct {
    char *value;
} ast_token_t;

ast_token_t *ast_token_alloc(char const *value);
void ast_token_free(ast_token_t *token);

/* ast_stmt_t */

typedef enum {
    STMT_CALL,
    STMT_COMMENT,
} ast_stmt_type_t;

typedef struct ast_stmt {
    ast_stmt_type_t type;

    union {
        struct {
            ast_token_t *target;
        } call;
        ast_comment_t *comment;
    };

    struct ast_stmt *next;
} ast_stmt_t;

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);

/* ast_t */

typedef struct {
    ast_stmt_t *stmts;
} ast_t;

ast_t *ast_alloc(void);
void ast_append(ast_t *ast, void *x);
void ast_append_stmt(ast_t *ast, ast_stmt_t *stmt);
void ast_pp(ast_t *ast);
void ast_free(ast_t *ast);

/* flex/bison */

int yylex(void);
int yyparse(ast_t *ast);
int yywrap(void);
void yyerror(ast_t *ast, char const *s);

int parser_test(void);

/* from lang.l */