Last active
August 29, 2015 14:14
-
-
Save mattn/95fa5d865ff294d8fc0a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/Makefile b/Makefile | |
index cfc9bd3..48670db 100644 | |
--- a/Makefile | |
+++ b/Makefile | |
@@ -1,6 +1,8 @@ | |
YACC = bison -y | |
LEX = flex | |
TARGET = bin/streem | |
+CFLAGS = -Wall | |
+LIBS = | |
ifeq (Windows_NT,$(OS)) | |
TARGET:=$(TARGET).exe | |
@@ -26,9 +28,9 @@ src/lex.yy.c : src/lex.l | |
src/parse.o : src/y.tab.c src/lex.yy.c | |
$(CC) -g -c src/y.tab.c -o src/parse.o | |
-$(TARGET) : src/parse.o | |
+$(TARGET) : src/parse.o src/node.o | |
mkdir -p "$$(dirname $(TARGET))" | |
- $(CC) -g src/parse.o -o $(TARGET) | |
+ $(CC) $(CFLAGS) src/parse.o src/node.o -o $(TARGET) $(LIBS) | |
clean : | |
rm -f src/y.output src/y.tab.c | |
diff --git a/src/lex.l b/src/lex.l | |
index 72c6933..64ba8a3 100644 | |
--- a/src/lex.l | |
+++ b/src/lex.l | |
@@ -6,39 +6,10 @@ | |
%{ | |
#include <string.h> | |
+#include "strm.h" | |
#define YY_DECL int yylex(YYSTYPE *yylval, parser_state *p) | |
-static char* | |
-strdup0(const char *s) | |
-{ | |
- size_t len = strlen(s); | |
- char *p; | |
- | |
- p = (char*)malloc(len+1); | |
- if (p) { | |
- strcpy(p, s); | |
- } | |
- return p; | |
-} | |
- | |
-static char* | |
-strndup0(const char *s, size_t n) | |
-{ | |
- size_t i, len; | |
- const char *p = s; | |
- char *new; | |
- | |
- for (i=0; i<n && *p; i++,p++) | |
- ; | |
- new = (char*)malloc(i+1); | |
- if (new) { | |
- memcpy(new, s, i); | |
- new[i] = '\0'; | |
- } | |
- return new; | |
-} | |
- | |
static int | |
lex_return(parser_state *p, int c) | |
{ | |
@@ -84,7 +55,7 @@ true{TRAIL} LEX_RETURN(keyword_true); | |
false{TRAIL} LEX_RETURN(keyword_false); | |
[A-Za-z_][A-Za-z0-9_]* { | |
- yylval->str = strdup0(yytext); | |
+ yylval->nd = strm_string_new(yytext); | |
LEX_RETURN(identifier); | |
}; | |
@@ -97,12 +68,12 @@ false{TRAIL} LEX_RETURN(keyword_false); | |
(([1-9][0-9]*)|0)(\.[0-9]*)? { | |
double temp; | |
sscanf(yytext, "%lf", &temp); | |
- yylval->d = temp; | |
+ yylval->nd = strm_double_new(temp); | |
LEX_RETURN(lit_number); | |
}; | |
\"([^\\\"]|\\.)*\" { | |
- yylval->str = strndup0(yytext+1, strlen(yytext)-2); | |
+ yylval->nd = strm_string_len_new(yytext+1, strlen(yytext)-2); | |
LEX_RETURN(lit_string); | |
}; | |
diff --git a/src/node.c b/src/node.c | |
new file mode 100644 | |
index 0000000..0f42bd5 | |
--- /dev/null | |
+++ b/src/node.c | |
@@ -0,0 +1,96 @@ | |
+#include "strm.h" | |
+#include <string.h> | |
+ | |
+static char* | |
+strdup0(const char *s) | |
+{ | |
+ size_t len = strlen(s); | |
+ char *p; | |
+ | |
+ p = (char*)malloc(len+1); | |
+ if (p) { | |
+ strcpy(p, s); | |
+ } | |
+ return p; | |
+} | |
+ | |
+static char* | |
+strndup0(const char *s, size_t n) | |
+{ | |
+ size_t i; | |
+ const char *p = s; | |
+ char *new; | |
+ | |
+ for (i=0; i<n && *p; i++,p++) | |
+ ; | |
+ new = (char*)malloc(i+1); | |
+ if (new) { | |
+ memcpy(new, s, i); | |
+ new[i] = '\0'; | |
+ } | |
+ return new; | |
+} | |
+ | |
+strm_node* strm_value_new(strm_node* v) { | |
+ return NULL; | |
+} | |
+ | |
+strm_node* strm_array_new() { | |
+ return NULL; | |
+} | |
+ | |
+strm_node* strm_array_add(strm_node* arr, strm_node* node) { | |
+ return NULL; | |
+} | |
+ | |
+strm_node* strm_stmt_new() { | |
+ return NULL; | |
+} | |
+ | |
+strm_node* strm_let_new(strm_node* var, strm_node* node) { | |
+ return NULL; | |
+} | |
+ | |
+strm_node* strm_op_new(const char* op, strm_node* lhs, strm_node* rhs) { | |
+ return NULL; | |
+} | |
+ | |
+strm_node* strm_funcall_new(strm_id id, strm_node* args, strm_node* blk) { | |
+ return NULL; | |
+} | |
+ | |
+strm_node* strm_nil_value() { | |
+ return NULL; | |
+} | |
+ | |
+strm_node* strm_double_new(strm_double d) { | |
+ strm_node* node = malloc(sizeof(strm_node)); | |
+ node->type = STRM_NODE_VALUE; | |
+ node->value.t = STRM_VALUE_DOUBLE; | |
+ node->value.v.d = d; | |
+ return node; | |
+} | |
+ | |
+strm_node* strm_string_new(strm_string s) { | |
+ strm_node* node = malloc(sizeof(strm_node)); | |
+ node->type = STRM_NODE_VALUE; | |
+ node->value.t = STRM_VALUE_STRING; | |
+ node->value.v.s = strdup0(s); | |
+ return node; | |
+} | |
+ | |
+strm_node* strm_string_len_new(strm_string s, size_t l) { | |
+ strm_node* node = malloc(sizeof(strm_node)); | |
+ node->type = STRM_NODE_VALUE; | |
+ node->value.t = STRM_VALUE_STRING; | |
+ node->value.v.s = strndup0(s, l); | |
+ return node; | |
+} | |
+ | |
+strm_node* strm_ident_new(strm_id id) { | |
+ strm_node* node = malloc(sizeof(strm_node)); | |
+ node->type = STRM_NODE_IDENT; | |
+ node->value.t = STRM_VALUE_FIXNUM; | |
+ node->value.v.id = id; | |
+ return node; | |
+} | |
diff --git a/src/parse.y b/src/parse.y | |
index f97e8ee..c45f8ee 100644 | |
--- a/src/parse.y | |
+++ b/src/parse.y | |
@@ -5,23 +5,21 @@ | |
*/ | |
%{ | |
-typedef struct parser_state { | |
- int nerr; | |
- void *lval; | |
- const char *fname; | |
- int lineno; | |
- int tline; | |
-} parser_state; | |
- | |
#define YYDEBUG 1 | |
#define YYERROR_VERBOSE 1 | |
+ | |
+#include "strm.h" | |
%} | |
%union { | |
- double d; | |
- char *str; | |
+ strm_node *nd; | |
+ strm_id id; | |
} | |
+%type <nd> program compstmt | |
+%type <nd> stmts stmt expr args var primary primary0 opt_args opt_block block terms f_args opt_terms | |
+%type <id> identifier | |
+ | |
%pure-parser | |
%parse-param {parser_state *p} | |
%lex-param {p} | |
@@ -89,45 +87,134 @@ program : compstmt | |
compstmt : stmts opt_terms | |
; | |
-stmts : /* none */ | |
+stmts : | |
+ { | |
+ $$ = strm_array_new(); | |
+ } | |
| stmt | |
+ { | |
+ strm_array_add($$, $1); | |
+ } | |
| stmts terms stmt | |
+ { | |
+ strm_array_add($1, $3); | |
+ } | |
| error stmt | |
+ { | |
+ /* TODO */ | |
+ } | |
; | |
-stmt : var '=' stmt | |
+stmt : var '=' expr | |
+ { | |
+ $$ = strm_let_new($1, $3); | |
+ } | |
| keyword_emit opt_args | |
+ { | |
+ /* TODO */ | |
+ } | |
| keyword_return opt_args | |
+ { | |
+ /* TODO */ | |
+ } | |
| keyword_break | |
+ { | |
+ /* TODO */ | |
+ } | |
| expr | |
+ { | |
+ $$ = $1; | |
+ } | |
; | |
var : identifier | |
+ { | |
+ } | |
; | |
-expr : expr op_plus expr | |
+expr : expr op_plus expr | |
+ { | |
+ $$ = strm_op_new("+", $1, $3); | |
+ } | |
| expr op_minus expr | |
+ { | |
+ $$ = strm_op_new("-", $1, $3); | |
+ } | |
| expr op_mult expr | |
+ { | |
+ $$ = strm_op_new("*", $1, $3); | |
+ } | |
| expr op_div expr | |
+ { | |
+ $$ = strm_op_new("/", $1, $3); | |
+ } | |
| expr op_mod expr | |
+ { | |
+ $$ = strm_op_new("%", $1, $3); | |
+ } | |
| expr op_bar expr | |
+ { | |
+ $$ = strm_op_new("|", $1, $3); | |
+ } | |
| expr op_amper expr | |
+ { | |
+ $$ = strm_op_new("&", $1, $3); | |
+ } | |
| expr op_gt expr | |
+ { | |
+ $$ = strm_op_new("<", $1, $3); | |
+ } | |
| expr op_ge expr | |
+ { | |
+ $$ = strm_op_new("<=", $1, $3); | |
+ } | |
| expr op_lt expr | |
+ { | |
+ $$ = strm_op_new(">", $1, $3); | |
+ } | |
| expr op_le expr | |
+ { | |
+ $$ = strm_op_new(">=", $1, $3); | |
+ } | |
| expr op_eq expr | |
+ { | |
+ $$ = strm_op_new("==", $1, $3); | |
+ } | |
| expr op_neq expr | |
+ { | |
+ $$ = strm_op_new("!=", $1, $3); | |
+ } | |
| op_plus expr %prec '!' | |
+ { | |
+ $$ = strm_value_new($2); | |
+ } | |
| op_minus expr %prec '!' | |
+ { | |
+ $$ = strm_value_new($2); | |
+ } | |
| '!' expr | |
+ { | |
+ $$ = strm_op_new("!", NULL, $2); | |
+ } | |
| '~' expr | |
+ { | |
+ $$ = strm_op_new("~", NULL, $2); | |
+ } | |
| expr op_and expr | |
+ { | |
+ $$ = strm_op_new("&&", $1, $3); | |
+ } | |
| expr op_or expr | |
- | primary | |
- ; | |
+ { | |
+ $$ = strm_op_new("||", $1, $3); | |
+ } | |
+ | primary | |
+ { | |
+ $$ = $1; | |
+ } | |
+ ; | |
-condition : condition op_plus condition | |
+condition : condition op_plus condition | |
| condition op_minus condition | |
| condition op_mult condition | |
| condition op_div condition | |
@@ -140,7 +227,7 @@ condition : condition op_plus condition | |
| condition op_le condition | |
| condition op_eq condition | |
| condition op_neq condition | |
- | op_plus condition %prec '!' | |
+ | op_plus condition %prec '!' | |
| op_minus condition %prec '!' | |
| '!' condition | |
| '~' condition | |
@@ -158,40 +245,98 @@ opt_else : opt_elsif | |
; | |
opt_args : /* none */ | |
+ { | |
+ $$ = strm_array_new(); | |
+ } | |
| args | |
+ { | |
+ $$ = $1; | |
+ } | |
; | |
args : expr | |
+ { | |
+ $$ = strm_array_new(); | |
+ } | |
| args ',' expr | |
+ { | |
+ strm_array_add($1, $3); | |
+ } | |
; | |
-primary0 : lit_number | |
+primary0 : lit_number | |
+ { | |
+ /* TODO */ | |
+ } | |
| lit_string | |
+ { | |
+ /* TODO */ | |
+ } | |
| identifier | |
+ { | |
+ $$ = strm_ident_new($1); | |
+ } | |
| '(' expr ')' | |
+ { | |
+ /* TODO */ | |
+ } | |
| '[' args ']' | |
+ { | |
+ /* TODO */ | |
+ } | |
| '[' ']' | |
+ { | |
+ /* TODO */ | |
+ } | |
| '[' map_args ']' | |
+ { | |
+ /* TODO */ | |
+ } | |
| '[' ':' '}' | |
- | keyword_if condition '{' compstmt '}' opt_else | |
+ { | |
+ /* TODO */ | |
+ } | |
+ | keyword_if condition '{' compstmt '}' opt_else | |
+ { | |
+ /* TODO */ | |
+ } | |
| keyword_nil | |
+ { | |
+ /* TODO */ | |
+ } | |
| keyword_true | |
+ { | |
+ /* TODO */ | |
+ } | |
| keyword_false | |
+ { | |
+ /* TODO */ | |
+ } | |
; | |
-cond : primary0 | |
+cond : primary0 | |
| identifier '(' opt_args ')' | |
| cond '.' identifier '(' opt_args ')' | |
| cond '.' identifier | |
- ; | |
+ ; | |
-primary : primary0 | |
+primary : primary0 | |
+ { | |
+ $$ = $1; | |
+ } | |
| block | |
+ { | |
+ } | |
| identifier block | |
+ { | |
+ } | |
| identifier '(' opt_args ')' opt_block | |
+ { | |
+ $$ = strm_funcall_new($1, $3, $5); | |
+ } | |
| primary '.' identifier '(' opt_args ')' opt_block | |
| primary '.' identifier opt_block | |
- ; | |
+ ; | |
map : lit_string ':' expr | |
| identifier ':' expr | |
@@ -201,28 +346,64 @@ map_args : map | |
| map_args ',' map | |
; | |
-opt_block : /* none */ | |
- | block | |
- ; | |
+opt_block : /* none */ | |
+ { | |
+ $$ = strm_nil_value(); | |
+ } | |
+ | block | |
+ { | |
+ $$ = $1; | |
+ } | |
+ ; | |
block : '{' bparam compstmt '}' | |
- | '{' compstmt '}' | |
+ { | |
+ /* TODO */ | |
+ } | |
+ | '{' compstmt '}' | |
+ { | |
+ /* TODO */ | |
+ } | |
; | |
bparam : op_rasgn | |
+ { | |
+ /* TODO */ | |
+ } | |
| f_args op_rasgn | |
+ { | |
+ /* TODO */ | |
+ } | |
; | |
f_args : identifier | |
+ { | |
+ $$ = strm_array_new(); | |
+ } | |
| f_args ',' identifier | |
+ { | |
+ strm_array_add($$, $1); | |
+ } | |
; | |
opt_terms : /* none */ | |
+ { | |
+ $$ = strm_array_new(); | |
+ } | |
| terms | |
+ { | |
+ strm_array_add($$, $1); | |
+ } | |
; | |
terms : term | |
+ { | |
+ $$ = strm_array_new(); | |
+ } | |
| terms term {yyerrok;} | |
+ { | |
+ strm_array_add($$, $1); | |
+ } | |
; | |
term : ';' {yyerrok;} | |
@@ -254,6 +435,7 @@ syntax_check(FILE *f, const char *fname) | |
yyin = f; | |
n = yyparse(&state); | |
+ printf("%p\n", state.lval); | |
if (n == 0 && state.nerr == 0) { | |
printf("%s: Syntax OK\n", fname); | |
return 0; | |
diff --git a/src/strm.h b/src/strm.h | |
new file mode 100644 | |
index 0000000..bfc8d5f | |
--- /dev/null | |
+++ b/src/strm.h | |
@@ -0,0 +1,71 @@ | |
+#ifndef _STRM_H_ | |
+#define _STRM_H_ | |
+#include <stdlib.h> | |
+ | |
+typedef enum { | |
+ STRM_VALUE_BOOL, | |
+ STRM_VALUE_ARRAY, | |
+ STRM_VALUE_MAP, | |
+ STRM_VALUE_STRING, | |
+ STRM_VALUE_DOUBLE, | |
+ STRM_VALUE_FIXNUM, | |
+} strm_value_type; | |
+ | |
+typedef enum { | |
+ STRM_NODE_STMTS, | |
+ STRM_NODE_STMT, | |
+ STRM_NODE_EXPR, | |
+ STRM_NODE_BLOCK, | |
+ STRM_NODE_IDENT, | |
+ STRM_NODE_LET, | |
+ STRM_NODE_IF, | |
+ STRM_NODE_ELSE, | |
+ STRM_NODE_ELSEIF, | |
+ STRM_NODE_VAR, | |
+ STRM_NODE_CONST, | |
+ STRM_NODE_OP_PLUS, | |
+ STRM_NODE_VALUE, | |
+} strm_node_type; | |
+ | |
+typedef unsigned int strm_id; | |
+typedef double strm_double; | |
+typedef char* strm_string; | |
+ | |
+typedef struct { | |
+ strm_value_type t; | |
+ union { | |
+ int b; | |
+ int i; | |
+ double d; | |
+ char* s; | |
+ void* p; | |
+ strm_id id; | |
+ } v; | |
+} strm_value; | |
+ | |
+typedef struct { | |
+ strm_node_type type; | |
+ strm_value value; | |
+} strm_node; | |
+ | |
+typedef struct parser_state { | |
+ int nerr; | |
+ void *lval; | |
+ const char *fname; | |
+ int lineno; | |
+ int tline; | |
+} parser_state; | |
+ | |
+extern strm_node* strm_value_new(strm_node* v); | |
+extern strm_node* strm_array_new(); | |
+extern strm_node* strm_array_add(strm_node*, strm_node*); | |
+extern strm_node* strm_stmt_new(); | |
+extern strm_node* strm_let_new(strm_node*, strm_node*); | |
+extern strm_node* strm_op_new(const char*, strm_node*, strm_node*); | |
+extern strm_node* strm_funcall_new(strm_id, strm_node*, strm_node*); | |
+extern strm_node* strm_nil_value(); | |
+extern strm_node* strm_double_new(strm_double); | |
+extern strm_node* strm_string_new(strm_string); | |
+extern strm_node* strm_string_len_new(strm_string, size_t); | |
+extern strm_node* strm_ident_new(strm_id); | |
+#endif /* _STRM_H_ */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment