Skip to content

Instantly share code, notes, and snippets.

@mattn
Last active August 29, 2015 14:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mattn/95fa5d865ff294d8fc0a to your computer and use it in GitHub Desktop.
Save mattn/95fa5d865ff294d8fc0a to your computer and use it in GitHub Desktop.
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