~lbnz/xr0

23ee8f3d16639888fd141587316ea5e8361f9f30 — Xr0 Team 6 months ago ec5162f
checkpoint
M Makefile => Makefile +15 -4
@@ 65,16 65,27 @@ $(XR0V): $(MAIN_OBJ) $(BIN_DIR)
	@printf 'CC\t$@\n'
	@$(CC) $(CFLAGS) -o $@ $(MAIN_OBJ) $(OBJECTS)

lex: $(XR0V)
	$(VALGRIND) $(XR0V) -I libx tests/3-program/100-lex/parse.x

lex-leaks: $(XR0V)
	$(VALGRIND) --leak-check=full \
		$(XR0V) -I libx tests/3-program/100-lex/parse.x

lex-verbose: $(XR0V) 
	$(VALGRIND) --num-callers=30 \
		$(XR0V) -I libx tests/3-program/100-lex/parse.x

matrix: $(XR0V)
	$(VALGRIND) $(XR0V) -I libx tests/3-program/matrix.x
	$(VALGRIND) $(XR0V) -I libx tests/3-program/000-matrix.x

matrix-leaks: $(XR0V)
	$(VALGRIND) --leak-check=full \
		$(XR0V) -I libx tests/3-program/matrix.x
		$(XR0V) -I libx tests/3-program/000-matrix.x

matrix-verbose: $(XR0V) 
	$(VALGRIND) --num-callers=30 \
		$(XR0V) -I libx tests/3-program/matrix.x
		$(XR0V) -I libx tests/3-program/000-matrix.x

$(MAIN_OBJ): main.c $(OBJECTS)
	@printf 'CC\t$@\n'


@@ 116,7 127,7 @@ $(UTIL_OBJ): $(UTIL_DIR)/util.c $(BUILD_DIR)
	@printf 'CC\t$@\n'
	@$(CC) $(CFLAGS) -o $@ -c $(UTIL_DIR)/util.c

$(AST_OBJ): $(AST_DIR)/ast.c $(AST_DIR)/expr/expr.h $(MATH_OBJ)
$(AST_OBJ): $(AST_DIR)/ast.c $(AST_DIR)/expr/expr.h $(AST_DIR)/literals.h $(MATH_OBJ)
	@printf 'CC\t$@\n'
	@$(CC) $(CFLAGS) -o $@ -c $(AST_DIR)/ast.c


M libx/stdio.h => libx/stdio.h +2 -0
@@ 1,6 1,8 @@
#ifndef STDIO_H
#define STDIO_H

typedef struct FILE; 

axiom int
putc(int c);


M src/ast/ast.c => src/ast/ast.c +1 -0
@@ 14,6 14,7 @@
#include "variable.c"
#include "function.c"
#include "externdecl.c"
#include "literals.c"

struct ast *
ast_create(struct ast_externdecl *decl)

M src/ast/gram.y => src/ast/gram.y +5 -24
@@ 8,6 8,7 @@
#include "expr/expr.h"
#include "gram_util.h"
#include "lex.h"
#include "literals.h"
#include "util.h"

extern char *yytext;


@@ 19,25 20,6 @@ int
yyerror();

/* XXX */
int
int_constant(char *s)
{
	int n = 0;
	for (; *s; s++) {
		n = 10*n + ((int) *s - '0');
	}
	return n;
}

/* XXX */
int
char_constant(char *s)
{
	assert(strlen(s) == 3 && s[0] == '\'' && s[2] == '\'');
	return s[1];
}

/* XXX */
char *
strip_quotes(char *s)
{


@@ 108,7 90,6 @@ variable_array_create(struct ast_variable *v)
%token AND_OP OR_OP MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN ADD_ASSIGN
%token SUB_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN
%token XOR_ASSIGN OR_ASSIGN TYPE_NAME
%token PREDICATE

%token TYPEDEF EXTERN STATIC AUTO REGISTER
%token CHAR SHORT INT LONG SIGNED UNSIGNED FLOAT DOUBLE CONST VOLATILE VOID


@@ 206,9 187,9 @@ primary_expression
	| ARB_ARG
		{ $$ = ast_expr_arbarg_create(); }
	| CONSTANT
		{ $$ = ast_expr_constant_create(int_constant(yytext)); } /* XXX */
		{ $$ = ast_expr_constant_create(parse_int(yytext)); } /* XXX */
	| CHAR_LITERAL
		{ $$ = ast_expr_constant_create(char_constant(yytext)); }
		{ $$ = ast_expr_constant_create(parse_char(yytext)); }
	| STRING_LITERAL
		{ $$ = ast_expr_literal_create(strip_quotes(yytext)); }
	| '(' expression ')'


@@ 299,7 280,7 @@ multiplicative_expression
additive_expression
	: multiplicative_expression
	| additive_expression '+' multiplicative_expression
	/*| additive_expression '-' multiplicative_expression*/
	| additive_expression '-' multiplicative_expression
	;

shift_expression


@@ 359,7 340,7 @@ logical_and_expression

logical_or_expression
	: logical_and_expression
	/*| logical_or_expression OR_OP logical_and_expression*/
	| logical_or_expression OR_OP logical_and_expression
	;

conditional_expression

A src/ast/literals.c => src/ast/literals.c +50 -0
@@ 0,0 1,50 @@
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <assert.h>
#include "literals.h"

int
parse_int(char *s)
{
	/* XXX */
	int n = 0;
	for (; *s; s++) {
		n = 10*n + ((int) *s - '0');
	}
	return n;
}

int
parse_escape(char c);

int
parse_char(char *s)
{
	/* literal must be nonempty and begin in a quote */
	assert(strlen(s) >= 3 && s[0] == '\'');

	switch (s[1]) {
	case '\\':
		assert(s[3] == '\'');
		return parse_escape(s[2]);
	default:
		assert(s[2] == '\'');
		return s[1];
	}
}

int
parse_escape(char c)
{
	switch (c) {
	case '0':
		return '\0';
	case 't':
		return '\t';
	case 'n':
		return '\t';
	default:
		assert(false);
	}
}

A src/ast/literals.h => src/ast/literals.h +10 -0
@@ 0,0 1,10 @@
#ifndef XR0_AST_LITERALS_H
#define XR0_AST_LITERALS_H

int
parse_int(char *s);

int
parse_char(char *s);

#endif

M tests/3-program/100-lex/parse.x => tests/3-program/100-lex/parse.x +153 -92
@@ 1,8 1,5 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <ctype.h>

char *
read_file(char *path);


@@ 21,9 18,12 @@ lexer_print(struct lexer *);
int
main()
{
	char *file = read_file("gen.l");
	char *file;
	struct lexer *;

	struct lexer *l = parse(file);
	file = read_file("gen.l");

	l = parse(file);
	lexer_print(l);
	lexer_destroy(l);



@@ 33,11 33,15 @@ main()
char *
read_file(char *path)
{
	FILE *f = fopen(path, "rb");
	FILE *f;
	char *str;
	int fsize; /* XXX: should be long */

	f = fopen(path, "rb");
	fseek(f, 0, SEEK_END);
	long fsize = ftell(f);
	fsize = ftell(f);
	fseek(f, 0, SEEK_SET);  /* same as rewind(f); */
	char *str = malloc(fsize + 1);
	str = malloc(fsize + 1);
	fread(str, fsize, 1, f);
	fclose(f);
	str[fsize] = '\0';


@@ 52,7 56,7 @@ void
pattern_print(struct pattern *);

struct token {
	bool literal;
	int isliteral;
	char *name; char *action;
};



@@ 69,13 73,16 @@ struct lexer *
lexer_create(char *pre, char *post, int npat, struct pattern *pattern,
		int ntok, struct token *token)
{
	struct lexer *l = (struct lexer *) malloc(sizeof(struct lexer));
	struct lexer *l;

	l = malloc(sizeof(struct lexer));
	l->pre = pre;
	l->post = post;
	l->pattern = pattern;
	l->npat = npat;
	l->token = token;
	l->ntok = ntok;

	return l;
}



@@ 90,16 97,18 @@ lexer_destroy(struct lexer *l)
void
lexer_print(struct lexer *l)
{
	int i;

	printf("\tpre: %s\n", l->pre);
	printf("\tpost: %s\n", l->post);
	printf("\tpatterns:\n");
	for (int i = 0; i < l->npat; i++) {
	for (i = 0; i < l->npat; i++) {
		printf("\t\t");
		pattern_print(&l->pattern[i]);
		printf("\n");
	}
	printf("\ttokens:\n");
	for (int i = 0; i < l->ntok; i++) {
	for (i = 0; i < l->ntok; i++) {
		printf("\t\t");
		token_print(&l->token[i]);
		printf("\n");


@@ 107,35 116,39 @@ lexer_print(struct lexer *l)
}

/* skipws: skip whitespace */
static char *
char *
skipws(char *s);

struct defsresult {
	char *pre;
	struct pattern *pattern;
	size_t npat;
	int npat;
	char *pos;
};

static struct defsresult
struct defsresult
parse_defs(char *pos);

struct rulesresult {
	struct token *token;
	size_t ntok;
	int ntok;
	char *pos;
};

static struct rulesresult
struct rulesresult
parse_rules(char *pos);

static char *
char *
parse_toeof(char *input);

struct lexer *
parse(char *pos)
{
	struct defsresult def = parse_defs(pos);
	struct defsresult def;
	struct rulesresult res;
	char *post;

	def = parse_defs(pos);
	pos = def.pos;
	if (strncmp(pos, "%%", 2) != 0) {
		fprintf(stderr, "invalid transition to rules: '%.*s'\n", 10,


@@ 143,9 156,9 @@ parse(char *pos)
		exit(1);
	}
	pos = skipws(pos + 2); /* %% */
	struct rulesresult res = parse_rules(pos);
	res = parse_rules(pos);
	pos = res.pos;
	char *post = "";
	post = "";
	if (strncmp(pos, "%%", 2) == 0) {
		pos += 2;
		post = parse_toeof(pos);


@@ 154,66 167,75 @@ parse(char *pos)
		res.token);
}

static char *
char *
substr(char *s, int n)
{
	int len = n + 1;
	char *ss = (char *) malloc(sizeof(char) * len);
	int len;
	char *ss;

	len = n + 1;
	ss = malloc(sizeof(char) * len);
	snprintf(ss, len, "%s", s);
	return ss;
}

static char *
char *
skipws(char *s)
{
	for (; isspace(*s); s++) {}
	return s;
}

static char *
char *
skiplinespace(char *s)
{
	for (; *s == ' ' || *s == '\t'; s++) {}
	return s;
}

static char *
char *
parse_id(char *input);

static char *
char *
skipoptions(char *pos)
{
	char *keyword = "%option";
	char *keyword;
	char *id;

	keyword = "%option";
	if (strncmp(pos, keyword, strlen(keyword)) != 0) {
		return pos;
	}
	pos += strlen(keyword);
	pos = skiplinespace(pos);
	char *id = parse_id(pos);
	id = parse_id(pos);
	pos += strlen(id);
	free(id);
	return pos;
}

static char *
char *
parse_id(char *input)
{
	char *s;

	if (!isalpha(*input)) {
		fprintf(stderr, "id must begin with letter: '%s'", input);
		exit(1);
	}
	char *s = input + 1;
	while (isalpha(*s) || isdigit(*s) || *s == '_') {
	s = input + 1;
	/* XXX: '0' is a placeholder to allow this to parse */
	for (; isalpha(*s) || isdigit(*s) || *s == '_' ; 0) {
		s++;
	}
	return substr(input, s - input);
}

static char *
char *
parse_tonewline(char *input)
{
	char *s = input;
	while (*s != '\n') {
	char *s;
	for (s = input; *s != '\n'; 0) {
		s++;
	}
	return substr(input, s - input);


@@ 224,56 246,72 @@ struct stringresult {
	char *pos;
};

static struct stringresult
struct stringresult
parse_defsraw(char *input);

struct patternet {
	struct pattern *pattern;
	size_t npat;
	int npat;
	char *pos;
};

static struct patternet
struct patternet
parse_defsproper(char *pos);

static struct defsresult
struct defsresult
parse_defs(char *pos)
{
	struct stringresult raw;
	struct patternet set;
	struct defsresult res;

	pos = skipws(pos);
	if (*pos == '\0') {
		fprintf(stderr, "EOF in defs\n");
		exit(1);
	}
	struct stringresult raw = parse_defsraw(pos);
	raw = parse_defsraw(pos);
	pos = raw.pos;
	pos = skipws(pos);
	pos = skipoptions(pos);
	pos = skipws(pos);
	struct patternet set = parse_defsproper(pos);
	return (struct defsresult) { raw.s, set.pattern, set.npat, set.pos };
	set = parse_defsproper(pos);

	res.pre = raw.s;
	res.pattern = set.patern;
	res.npat = set.npat;
	res.pos = set.pos;
	return res;
}

static struct stringresult
struct stringresult
parse_defsraw(char *input)
{
	char *pos;
	struct stringresult res;

	if (strncmp(input, "%{", 2) != 0) {
		return (struct stringresult){"", input};
		res.s = "";
		res.pos = input;
		return res;
	}
	input += 2;
	char *pos = input;
	pos = input;
	for (; strncmp(pos, "%}", 2) != 0; pos++) {}
	return (struct stringresult){
		substr(input, pos - input),
		pos + 2,
	};
	res.s = substr(input, pos - input);
	res.pos = pos + 2;
	return res;
}

struct pattern *
pattern_create(char *name, char *pattern)
{
	struct pattern *p = (struct pattern *) malloc(sizeof(struct pattern));
	struct pattern *p;

	p = malloc(sizeof(struct pattern));
	p->name = name;
	p->pattern = pattern;

	return p;
}



@@ 292,47 330,63 @@ struct patternresult {
struct patternresult
parse_pattern(char *pos);

static struct patternet
struct patternet
parse_defsproper(char *pos)
{
	size_t npat = 0;
	struct pattern *pattern = NULL;
	int npat;
	struct pattern *pattern;
	struct patternresult parsed;
	struct patternet res;

	npat = 0;
	pattern = NULL;
	for (; strncmp(pos, "%%", 2) != 0 ; npat++) {
		struct patternresult res = parse_pattern(pos);
		pos = res.pos;
		pattern = (struct pattern *)
			realloc(pattern, sizeof(struct pattern) * (npat + 1));
		pattern[npat] = *res.p;
		parsed = parse_pattern(pos);
		pos = parsed.pos;
		pattern = realloc(pattern, sizeof(struct pattern) * (npat + 1));
		pattern[npat] = *parsed.p;
		pos = skipws(pos);
	}
	return (struct patternet){pattern, npat, pos};
	res.pattern = pattern;
	res.npat = npat;
	res.pos = pos;
	return pos;
}

struct patternresult
parse_pattern(char *pos)
{
	char *name = parse_id(pos);
	char *name; char *pattern;
	struct patternresult res;

	name = parse_id(pos);
	pos = pos + strlen(name);
	pos = skiplinespace(pos);
	char *pattern = parse_tonewline(pos);
	pattern = parse_tonewline(pos);
	pos += strlen(pattern);
	return (struct patternresult){pattern_create(name, pattern), pos};

	res.p = pattern_create(name, pattern);
	res.pos = pos;
	return res;
}

static struct token *
token_create(bool literal, char *name, char *action)
struct token *
token_create(int isliteral, char *name, char *action)
{
	struct token *tk = (struct token *) malloc(sizeof(struct token));
	tk->literal = literal;
	struct token *tk;

	tk = malloc(sizeof(struct token));
	tk->isliteral = isliteral;
	tk->name = name;
	tk->action = action;

	return tk;
}

void
token_print(struct token *t)
{
	if (t->literal) {
	if (t->isliteral) {
		printf("\"%s\"", t->name);
	} else {
		printf("{%s}", t->name);


@@ 345,60 399,67 @@ struct tokenresult {
	char *pos;
};

static struct tokenresult
struct tokenresult
parse_token(char *pos);

static struct rulesresult
struct rulesresult
parse_rules(char *pos)
{
	size_t ntok = 0;
	struct token *token = NULL;
	int ntok;
	struct token *token;
	struct tokenresult parsed;
	struct rulesresult res;

	ntok = 0;
	token = NULL;
	for (; *pos != '\0' && strncmp(pos, "%%", 2) != 0 ; ntok++) {
		struct tokenresult res = parse_token(pos);
		pos = res.pos;
		token = (struct token *)
			realloc(token, sizeof(struct token) * (ntok + 1));
		token[ntok] = *res.tk;
		parsed = parse_token(pos);
		pos = parsed.pos;
		token = realloc(token, sizeof(struct token) * (ntok + 1));
		token[ntok] = *parsed.tk;
		pos = skipws(pos);
	}
	return (struct rulesresult) { token, ntok, pos };
	res.token = token;
	res.ntok = ntok;
	res.pos = pos;
	return res;
}

struct tknameresult {
	bool literal;
	int isliteral;
	char *name;
	char *pos;
};

typedef struct tknameresult (*nameparser)(char *);

static nameparser
nameparser
choose_nameparser(char *pos);

static struct stringresult
struct stringresult
parse_action(char *input);

static struct tokenresult
struct tokenresult
parse_token(char *pos)
{
	struct tknameresult nameres = choose_nameparser(pos)(pos);
	struct stringresult actionres = parse_action(skiplinespace(nameres.pos));
	return (struct tokenresult){
		token_create(nameres.literal, nameres.name, actionres.s),
		token_create(nameres.isliteral, nameres.name, actionres.s),
		actionres.pos,
	};
}

static struct tknameresult
struct tknameresult
parse_token_id(char *pos);

static struct tknameresult
struct tknameresult
parse_token_literal(char *input);

static struct tknameresult
struct tknameresult
parse_token_pattern(char *pos);

static nameparser
nameparser
choose_nameparser(char *pos)
{
	switch (*pos) {


@@ 411,7 472,7 @@ choose_nameparser(char *pos)
	}
}

static struct tknameresult
struct tknameresult
parse_token_id(char *pos)
{
	char *id = parse_id(++pos); /* skip '{' */


@@ 424,7 485,7 @@ parse_token_id(char *pos)
	return (struct tknameresult){false, id, pos + 1}; /* '}' */
}

static struct tknameresult
struct tknameresult
parse_token_literal(char *input)
{
	input++; /* skip '"' */


@@ 437,14 498,14 @@ parse_token_literal(char *input)
	};
}

static struct tknameresult
struct tknameresult
parse_token_pattern(char *pos)
{
	char *id = parse_id(pos);
	return (struct tknameresult){true, id, pos + strlen(id)};
}

static struct stringresult
struct stringresult
parse_action(char *input)
{
	if (*input != '{') {


@@ 462,7 523,7 @@ parse_action(char *input)

}

static char *
char *
parse_toeof(char *input)
{
	char *s = input;