r/o

d9a0d7a434006111c22850e83377d22d3f2f22eb parent fc1cb566

authored by Yuki Izumi <yuki@kivikakk.ee> 10 years ago
committed by Yuki Izumi <yuki@kivikakk.ee> 10 years ago

exprs (should be expr_imm or sth), print wip

lang.l | 3 ++-
lang.y | 15 ++++++++++++++-
parser.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
parser.h | 22 ++++++++++++++++++++++
4 files changed, 91 insertions(+), 4 deletions(-)
diff --git a/lang.l b/lang.l
index d83e59e..970b65c 100644
--- a/lang.l
+++ b/lang.l
@@ -5,8 +5,9 @@
%%
+\"[^"\n]+\"? { yylval.expr = ast_string_alloc(yytext + 1); return EXPR; }
REM[^\n]+ { yylval.comment = ast_comment_alloc(yytext + 3, 1); return COMMENT; }
-'[^\n]+ { yylval.comment = ast_comment_alloc(yytext + 1, 0); 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]; }
diff --git a/lang.y b/lang.y
index 2954f5e..b67c9c4 100644
--- a/lang.y
+++ b/lang.y
@@ -8,6 +8,7 @@
%union {
ast_comment_t *comment;
ast_token_t *token;
+ ast_expr_t *expr;
ast_stmt_t *stmt;
}
@@ -17,9 +18,11 @@
%token NL
%token <token> TOKEN
+%token <expr> EXPR
%token <comment> COMMENT
%type <stmt> line stmt
+%type <expr> exprlist opt_exprlist
%%
@@ -36,8 +39,18 @@ line: line_separator { $$ = 0; }
| stmt END_OF_FILE { $$ = $1; }
;
-stmt: TOKEN { $$ = ast_stmt_alloc(STMT_CALL); $$->call.target = $1; }
+stmt: TOKEN opt_exprlist { $$ = ast_stmt_alloc(STMT_CALL); $$->call.target = $1; $$->call.args = $2; }
| COMMENT { $$ = ast_stmt_alloc(STMT_COMMENT); $$->comment = $1; }
;
+exprlist: EXPR { $$ = $1; }
+ | exprlist ',' EXPR { $$ = $1; $1->next = $3; $1->nexttype = ','; }
+ | exprlist ';' EXPR { $$ = $1; $1->next = $3; $1->nexttype = ';'; }
+ | exprlist EXPR { $$ = $1; $1->next = $2; $1->nexttype = ';'; }
+;
+
+opt_exprlist: /* empty */ { $$ = 0; }
+ | exprlist { $$ = $1; }
+;
+
/* vim: set sw=4 et: */
diff --git a/parser.c b/parser.c
index 3c5a159..eb1681f 100644
--- a/parser.c
+++ b/parser.c
@@ -4,6 +4,45 @@
#include "parser.h"
+/* ast_expr_t */
+
+ast_expr_t *ast_string_alloc(char const *value) {
+ ast_expr_t *expr = malloc(sizeof(*expr));
+ memset(expr, 0, sizeof(*expr));
+ expr->type = EXPR_STRING;
+ expr->string = strdup(value);
+
+ int len = strlen(expr->string);
+ if (len > 0 && expr->string[len - 1] == '"') {
+ expr->string[len - 1] = 0;
+ }
+
+ return expr;
+}
+
+void ast_expr_pp(ast_expr_t *expr) {
+ switch (expr->type) {
+ case EXPR_STRING:
+ printf("\"%s\"", expr->string);
+ break;
+
+ default:
+ fprintf(stderr, "UNKNOWN EXPR TYPE %d\n", expr->type);
+ }
+}
+
+void ast_expr_free(ast_expr_t *expr) {
+ switch (expr->type) {
+ case EXPR_STRING:
+ free(expr->string);
+ break;
+
+ default:
+ break;
+ }
+ free(expr);
+}
+
/* ast_comment_t */
ast_comment_t *ast_comment_alloc(char const *value, int is_rem) {
@@ -45,7 +84,19 @@ ast_stmt_t *ast_stmt_alloc(ast_stmt_type_t type) {
void ast_stmt_pp(ast_stmt_t *stmt) {
switch (stmt->type) {
case STMT_CALL:
- printf("%s\n", stmt->call.target->value);
+ printf("%s", stmt->call.target->value);
+
+ ast_expr_t *args = stmt->call.args;
+ while (args) {
+ printf(" ");
+ ast_expr_pp(args);
+ if (args->next) {
+ printf("%c", args->nexttype);
+ }
+ args = args->next;
+ }
+
+ printf("\n");
break;
case STMT_COMMENT:
@@ -104,7 +155,7 @@ int parser_test(void) {
ast_t *ast = ast_alloc();
begin_scan(
- "PRINT\n"
+ "PRINT \"Hello\"; \"there\", \"pals\" \"!\"\n"
"GOTO\n"
"\n"
"REM Okay, sure thing.\n"
diff --git a/parser.h b/parser.h
index 643c6c1..5c08c98 100644
--- a/parser.h
+++ b/parser.h
@@ -1,6 +1,27 @@
#ifndef PARSER_H
#define PARSER_H
+/* ast_expr_t */
+
+typedef enum {
+ EXPR_STRING,
+} ast_expr_type_t;
+
+typedef struct ast_expr {
+ ast_expr_type_t type;
+
+ union {
+ char *string;
+ };
+
+ struct ast_expr *next;
+ char nexttype;
+} ast_expr_t;
+
+ast_expr_t *ast_string_alloc(char const *value);
+void ast_expr_pp(ast_expr_t *expr);
+void ast_expr_free(ast_expr_t *expr);
+
/* ast_comment_t */
typedef struct {
@@ -33,6 +54,7 @@ typedef struct ast_stmt {
union {
struct {
ast_token_t *target;
+ ast_expr_t *args;
} call;
ast_comment_t *comment;
};