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,
+ };
+};