~sircmpwn/ipcgen

37c690af8dcf590b82941d4c557c61e484d78b46 — Drew DeVault 2 months ago 1c9af18
parse: implement enums
7 files changed, 87 insertions(+), 2 deletions(-)

M ast/ast.ha
M ast/type.ha
M doc/grammar.txt
M gen/client.ha
M gen/server.ha
M parse/document.ha
A parse/enum.ha
M ast/ast.ha => ast/ast.ha +1 -0
@@ 3,6 3,7 @@ export type document = struct {
	namespace: ident,
	imports: []ident,
	interfaces: []interface,
	enums: []enum_,
	errors: []error,
};


M ast/type.ha => ast/type.ha +12 -0
@@ 17,3 17,15 @@ export type ptype = enum {

// An IPC type.
export type ipc_type = (str | ptype);

// An enumerated type.
export type enum_ = struct {
	name: str,
	membs: []enum_member,
};

// A member of an enumerated type.
export type enum_member = struct {
	name: str,
	val: (uint | void),
};

M doc/grammar.txt => doc/grammar.txt +1 -1
@@ 60,7 60,7 @@ unit
	"unit" word ["=" uint]

enum
	"enum" word ["=" uint] "{" 1*enum-members "}"
	"enum" word "{" 1*enum-members "}"

enum-members
	word ","

M gen/client.ha => gen/client.ha +13 -0
@@ 12,6 12,11 @@ export fn client(out: io::handle, doc: *ast::document) (void | io::error) = {
	fmt::fprintln(out, "use rt;")!;
	fmt::fprintln(out)!;

	for (let i = 0z; i < len(doc.enums); i += 1) {
		const em = &doc.enums[i];
		c_enum(out, doc, em)?;
	};

	for (let i = 0z; i < len(doc.interfaces); i += 1) {
		const iface = &doc.interfaces[i];
		c_iface(out, doc, iface)?;


@@ 160,3 165,11 @@ fn c_meth(
	)?;
	fmt::fprintln(out)?;
};

fn c_enum(
	out: io::handle,
	doc: *ast::document,
	em: *ast::enum_,
) (void | io::error) = {
	abort(); // TODO
};

M gen/server.ha => gen/server.ha +13 -0
@@ 14,6 14,11 @@ export fn server(out: io::handle, doc: *ast::document) (void | io::error) = {
	fmt::fprintln(out, "use rt;")!;
	fmt::fprintln(out)!;

	for (let i = 0z; i < len(doc.enums); i += 1) {
		const em = &doc.enums[i];
		s_enum(out, doc, em)?;
	};

	for (let i = 0z; i < len(doc.interfaces); i += 1) {
		const iface = &doc.interfaces[i];
		s_iface(out, doc, iface)?;


@@ 320,3 325,11 @@ fn s_method_dispatch(
		("params_out", params_out),
	)?;
};

fn s_enum(
	out: io::handle,
	doc: *ast::document,
	em: *ast::enum_,
) (void | io::error) = {
	abort(); // TODO
};

M parse/document.ha => parse/document.ha +2 -1
@@ 26,7 26,8 @@ export fn document(lex: *lex::lexer) (ast::document | error) = {
		case ltok::UNIT =>
			abort(); // TODO
		case ltok::ENUM =>
			abort(); // TODO
			const enum_ = enum_(lex)?;
			append(doc.enums, enum_);
		case ltok::ERROR =>
			const err = parse_error(lex)?;
			append(doc.errors, err);

A parse/enum.ha => parse/enum.ha +45 -0
@@ 0,0 1,45 @@
use ast;
use lex;
use lex::{ltok};
use strings;

fn enum_(lex: *lex::lexer) (ast::enum_ | error) = {
	let em = ast::enum_ {
		name = strings::dup(want(lex, ltok::WORD)?.1 as str),
		...
	};

	want(lex, ltok::LBRACE)?;

	for (true) {
		const memb = enum_member(lex)?;
		append(em.membs, memb);

		if (try(lex, ltok::RBRACE)? is lex::token) {
			break;
		};
	};

	want(lex, ltok::SEMICOLON)?;
	return em;
};

fn enum_member(lex: *lex::lexer) (ast::enum_member | error) = {
	const name = strings::dup(want(lex, ltok::WORD)?.1 as str);

	let val: (void | uint) = void;
	if (try(lex, ltok::EQUAL) is lex::token) {
		val = want(lex, ltok::INTEGER)?.1 as uint;
	};

	if (try(lex, ltok::LSHIFT)? is lex::token) {
		abort(); // TODO
	};

	want(lex, ltok::COMMA)?;

	return ast::enum_member {
		name = name,
		val = val,
	};
};