Sigrid Solveig HaflínudóttirPlan 9 portf9452535 years agoHistory
1069 lines · 23.7 KB · C
RawDownload
#include "jsi.h"#include "jslex.h"#include "jsparse.h" #define LIST(h)			jsP_newnode(J, AST_LIST, 0, h, 0, 0, 0) #define EXP0(x)			jsP_newnode(J, EXP_ ## x, line, 0, 0, 0, 0)#define EXP1(x,a)		jsP_newnode(J, EXP_ ## x, line, a, 0, 0, 0)#define EXP2(x,a,b)		jsP_newnode(J, EXP_ ## x, line, a, b, 0, 0)#define EXP3(x,a,b,c)		jsP_newnode(J, EXP_ ## x, line, a, b, c, 0) #define STM0(x)			jsP_newnode(J, STM_ ## x, line, 0, 0, 0, 0)#define STM1(x,a)		jsP_newnode(J, STM_ ## x, line, a, 0, 0, 0)#define STM2(x,a,b)		jsP_newnode(J, STM_ ## x, line, a, b, 0, 0)#define STM3(x,a,b,c)		jsP_newnode(J, STM_ ## x, line, a, b, c, 0)#define STM4(x,a,b,c,d)		jsP_newnode(J, STM_ ## x, line, a, b, c, d) static js_Ast *expression(js_State *J, int notin);static js_Ast *assignment(js_State *J, int notin);static js_Ast *memberexp(js_State *J);static js_Ast *statement(js_State *J);static js_Ast *funbody(js_State *J); JS_NORETURN static void *jsP_error(js_State *J, const char *fmt, ...) JS_PRINTFLIKE(2,3); #define INCREC() if (++J->astdepth > JS_ASTLIMIT) jsP_error(J, "too much recursion")#define DECREC() --J->astdepth#define SAVEREC() int SAVE=J->astdepth#define POPREC() J->astdepth=SAVE static void *jsP_error(js_State *J, const char *fmt, ...){	va_list ap;	char buf[512];	char msgbuf[256]; 	va_start(ap, fmt);	vsnprintf(msgbuf, 256, fmt, ap);	va_end(ap); 	snprintf(buf, 256, "%s:%d: ", J->filename, J->lexline);	strcat(buf, msgbuf); 	js_newsyntaxerror(J, buf);	js_throw(J); 	return NULL;} static void jsP_warning(js_State *J, const char *fmt, ...){	va_list ap;	char buf[512];	char msg[256]; 	va_start(ap, fmt);	vsnprintf(msg, sizeof msg, fmt, ap);	va_end(ap); 	snprintf(buf, sizeof buf, "%s:%d: warning: %s", J->filename, J->lexline, msg);	js_report(J, buf);} static js_Ast *jsP_newnode(js_State *J, enum js_AstType type, int line, js_Ast *a, js_Ast *b, js_Ast *c, js_Ast *d){	js_Ast *node = js_malloc(J, sizeof *node); 	node->type = type;	node->line = line;	node->a = a;	node->b = b;	node->c = c;	node->d = d;	node->number = 0;	node->string = NULL;	node->jumps = NULL;	node->casejump = 0; 	node->parent = NULL;	if (a) a->parent = node;	if (b) b->parent = node;	if (c) c->parent = node;	if (d) d->parent = node; 	node->gcnext = J->gcast;	J->gcast = node; 	return node;} static js_Ast *jsP_list(js_Ast *head){	/* set parent pointers in list nodes */	js_Ast *prev = head, *node = head->b;	while (node) {		node->parent = prev;		prev = node;		node = node->b;	}	return head;} static js_Ast *jsP_newstrnode(js_State *J, enum js_AstType type, const char *s){	js_Ast *node = jsP_newnode(J, type, J->lexline, 0, 0, 0, 0);	node->string = s;	return node;} static js_Ast *jsP_newnumnode(js_State *J, enum js_AstType type, double n){	js_Ast *node = jsP_newnode(J, type, J->lexline, 0, 0, 0, 0);	node->number = n;	return node;} static void jsP_freejumps(js_State *J, js_JumpList *node){	while (node) {		js_JumpList *next = node->next;		js_free(J, node);		node = next;	}} void jsP_freeparse(js_State *J){	js_Ast *node = J->gcast;	while (node) {		js_Ast *next = node->gcnext;		jsP_freejumps(J, node->jumps);		js_free(J, node);		node = next;	}	J->gcast = NULL;} /* Lookahead */ static void jsP_next(js_State *J){	J->lookahead = jsY_lex(J);} #define jsP_accept(J,x) (J->lookahead == x ? (jsP_next(J), 1) : 0) #define jsP_expect(J,x) if (!jsP_accept(J, x)) jsP_error(J, "unexpected token: %s (expected %s)", jsY_tokenstring(J->lookahead), jsY_tokenstring(x)) static void semicolon(js_State *J){	if (J->lookahead == ';') {		jsP_next(J);		return;	}	if (J->newline || J->lookahead == '}' || J->lookahead == 0)		return;	jsP_error(J, "unexpected token: %s (expected ';')", jsY_tokenstring(J->lookahead));} /* Literals */ static js_Ast *identifier(js_State *J){	js_Ast *a;	if (J->lookahead == TK_IDENTIFIER) {		a = jsP_newstrnode(J, AST_IDENTIFIER, J->text);		jsP_next(J);		return a;	}	return jsP_error(J, "unexpected token: %s (expected identifier)", jsY_tokenstring(J->lookahead));} static js_Ast *identifieropt(js_State *J){	if (J->lookahead == TK_IDENTIFIER)		return identifier(J);	return NULL;} static js_Ast *identifiername(js_State *J){	if (J->lookahead == TK_IDENTIFIER || J->lookahead >= TK_BREAK) {		js_Ast *a = jsP_newstrnode(J, AST_IDENTIFIER, J->text);		jsP_next(J);		return a;	}	return jsP_error(J, "unexpected token: %s (expected identifier or keyword)", jsY_tokenstring(J->lookahead));} static js_Ast *arrayelement(js_State *J){	int line = J->lexline;	if (J->lookahead == ',')		return EXP0(UNDEF);	return assignment(J, 0);} static js_Ast *arrayliteral(js_State *J){	js_Ast *head, *tail;	if (J->lookahead == ']')		return NULL;	head = tail = LIST(arrayelement(J));	while (jsP_accept(J, ',')) {		if (J->lookahead != ']')			tail = tail->b = LIST(arrayelement(J));	}	return jsP_list(head);} static js_Ast *propname(js_State *J){	js_Ast *name;	if (J->lookahead == TK_NUMBER) {		name = jsP_newnumnode(J, EXP_NUMBER, J->number);		jsP_next(J);	} else if (J->lookahead == TK_STRING) {		name = jsP_newstrnode(J, EXP_STRING, J->text);		jsP_next(J);	} else {		name = identifiername(J);	}	return name;} static js_Ast *propassign(js_State *J){	js_Ast *name, *value, *arg, *body;	int line = J->lexline; 	name = propname(J); 	if (J->lookahead != ':' && name->type == AST_IDENTIFIER) {		if (!strcmp(name->string, "get")) {			name = propname(J);			jsP_expect(J, '(');			jsP_expect(J, ')');			body = funbody(J);			return EXP3(PROP_GET, name, NULL, body);		}		if (!strcmp(name->string, "set")) {			name = propname(J);			jsP_expect(J, '(');			arg = identifier(J);			jsP_expect(J, ')');			body = funbody(J);			return EXP3(PROP_SET, name, LIST(arg), body);		}	} 	jsP_expect(J, ':');	value = assignment(J, 0);	return EXP2(PROP_VAL, name, value);} static js_Ast *objectliteral(js_State *J){	js_Ast *head, *tail;	if (J->lookahead == '}')		return NULL;	head = tail = LIST(propassign(J));	while (jsP_accept(J, ',')) {		if (J->lookahead == '}')			break;		tail = tail->b = LIST(propassign(J));	}	return jsP_list(head);} /* Functions */ static js_Ast *parameters(js_State *J){	js_Ast *head, *tail;	if (J->lookahead == ')')		return NULL;	head = tail = LIST(identifier(J));	while (jsP_accept(J, ',')) {		tail = tail->b = LIST(identifier(J));	}	return jsP_list(head);} static js_Ast *fundec(js_State *J, int line){	js_Ast *a, *b, *c;	a = identifier(J);	jsP_expect(J, '(');	b = parameters(J);	jsP_expect(J, ')');	c = funbody(J);	return jsP_newnode(J, AST_FUNDEC, line, a, b, c, 0);} static js_Ast *funstm(js_State *J, int line){	js_Ast *a, *b, *c;	a = identifier(J);	jsP_expect(J, '(');	b = parameters(J);	jsP_expect(J, ')');	c = funbody(J);	/* rewrite function statement as "var X = function X() {}" */	return STM1(VAR, LIST(EXP2(VAR, a, EXP3(FUN, a, b, c))));} static js_Ast *funexp(js_State *J, int line){	js_Ast *a, *b, *c;	a = identifieropt(J);	jsP_expect(J, '(');	b = parameters(J);	jsP_expect(J, ')');	c = funbody(J);	return EXP3(FUN, a, b, c);} /* Expressions */ static js_Ast *primary(js_State *J){	js_Ast *a;	int line = J->lexline; 	if (J->lookahead == TK_IDENTIFIER) {		a = jsP_newstrnode(J, EXP_IDENTIFIER, J->text);		jsP_next(J);		return a;	}	if (J->lookahead == TK_STRING) {		a = jsP_newstrnode(J, EXP_STRING, J->text);		jsP_next(J);		return a;	}	if (J->lookahead == TK_REGEXP) {		a = jsP_newstrnode(J, EXP_REGEXP, J->text);		a->number = J->number;		jsP_next(J);		return a;	}	if (J->lookahead == TK_NUMBER) {		a = jsP_newnumnode(J, EXP_NUMBER, J->number);		jsP_next(J);		return a;	} 	if (jsP_accept(J, TK_THIS)) return EXP0(THIS);	if (jsP_accept(J, TK_NULL)) return EXP0(NULL);	if (jsP_accept(J, TK_TRUE)) return EXP0(TRUE);	if (jsP_accept(J, TK_FALSE)) return EXP0(FALSE);	if (jsP_accept(J, '{')) {		a = EXP1(OBJECT, objectliteral(J));		jsP_expect(J, '}');		return a;	}	if (jsP_accept(J, '[')) {		a = EXP1(ARRAY, arrayliteral(J));		jsP_expect(J, ']');		return a;	}	if (jsP_accept(J, '(')) {		a = expression(J, 0);		jsP_expect(J, ')');		return a;	} 	return jsP_error(J, "unexpected token in expression: %s", jsY_tokenstring(J->lookahead));} static js_Ast *arguments(js_State *J){	js_Ast *head, *tail;	if (J->lookahead == ')')		return NULL;	head = tail = LIST(assignment(J, 0));	while (jsP_accept(J, ',')) {		tail = tail->b = LIST(assignment(J, 0));	}	return jsP_list(head);} static js_Ast *newexp(js_State *J){	js_Ast *a, *b;	int line = J->lexline; 	if (jsP_accept(J, TK_NEW)) {		a = memberexp(J);		if (jsP_accept(J, '(')) {			b = arguments(J);			jsP_expect(J, ')');			return EXP2(NEW, a, b);		}		return EXP1(NEW, a);	} 	if (jsP_accept(J, TK_FUNCTION))		return funexp(J, line); 	return primary(J);} static js_Ast *memberexp(js_State *J){	js_Ast *a = newexp(J);	int line;	SAVEREC();loop:	INCREC();	line = J->lexline;	if (jsP_accept(J, '.')) { a = EXP2(MEMBER, a, identifiername(J)); goto loop; }	if (jsP_accept(J, '[')) { a = EXP2(INDEX, a, expression(J, 0)); jsP_expect(J, ']'); goto loop; }	POPREC();	return a;} static js_Ast *callexp(js_State *J){	js_Ast *a = newexp(J);	int line;	SAVEREC();loop:	INCREC();	line = J->lexline;	if (jsP_accept(J, '.')) { a = EXP2(MEMBER, a, identifiername(J)); goto loop; }	if (jsP_accept(J, '[')) { a = EXP2(INDEX, a, expression(J, 0)); jsP_expect(J, ']'); goto loop; }	if (jsP_accept(J, '(')) { a = EXP2(CALL, a, arguments(J)); jsP_expect(J, ')'); goto loop; }	POPREC();	return a;} static js_Ast *postfix(js_State *J){	js_Ast *a = callexp(J);	int line = J->lexline;	if (!J->newline && jsP_accept(J, TK_INC)) return EXP1(POSTINC, a);	if (!J->newline && jsP_accept(J, TK_DEC)) return EXP1(POSTDEC, a);	return a;} static js_Ast *unary(js_State *J){	js_Ast *a;	int line = J->lexline;	INCREC();	if (jsP_accept(J, TK_DELETE)) a = EXP1(DELETE, unary(J));	else if (jsP_accept(J, TK_VOID)) a = EXP1(VOID, unary(J));	else if (jsP_accept(J, TK_TYPEOF)) a = EXP1(TYPEOF, unary(J));	else if (jsP_accept(J, TK_INC)) a = EXP1(PREINC, unary(J));	else if (jsP_accept(J, TK_DEC)) a = EXP1(PREDEC, unary(J));	else if (jsP_accept(J, '+')) a = EXP1(POS, unary(J));	else if (jsP_accept(J, '-')) a = EXP1(NEG, unary(J));	else if (jsP_accept(J, '~')) a = EXP1(BITNOT, unary(J));	else if (jsP_accept(J, '!')) a = EXP1(LOGNOT, unary(J));	else a = postfix(J);	DECREC();	return a;} static js_Ast *multiplicative(js_State *J){	js_Ast *a = unary(J);	int line;	SAVEREC();loop:	INCREC();	line = J->lexline;	if (jsP_accept(J, '*')) { a = EXP2(MUL, a, unary(J)); goto loop; }	if (jsP_accept(J, '/')) { a = EXP2(DIV, a, unary(J)); goto loop; }	if (jsP_accept(J, '%')) { a = EXP2(MOD, a, unary(J)); goto loop; }	POPREC();	return a;} static js_Ast *additive(js_State *J){	js_Ast *a = multiplicative(J);	int line;	SAVEREC();loop:	INCREC();	line = J->lexline;	if (jsP_accept(J, '+')) { a = EXP2(ADD, a, multiplicative(J)); goto loop; }	if (jsP_accept(J, '-')) { a = EXP2(SUB, a, multiplicative(J)); goto loop; }	POPREC();	return a;} static js_Ast *shift(js_State *J){	js_Ast *a = additive(J);	int line;	SAVEREC();loop:	INCREC();	line = J->lexline;	if (jsP_accept(J, TK_SHL)) { a = EXP2(SHL, a, additive(J)); goto loop; }	if (jsP_accept(J, TK_SHR)) { a = EXP2(SHR, a, additive(J)); goto loop; }	if (jsP_accept(J, TK_USHR)) { a = EXP2(USHR, a, additive(J)); goto loop; }	POPREC();

Lines 1–500 of 1069.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t