/* agrampar.y see license.txt for copyright and terms of use * parser for abstract grammar definitions (.ast files) */ /* C declarations */ %{ #include "agrampar.h" // agrampar_yylex, etc. #include // malloc, free #include // cout // enable debugging the parser #ifndef NDEBUG #define YYDEBUG 1 #endif // permit having other parser's codes in the same program #define yyparse agrampar_yyparse %} /* ================== bison declarations =================== */ // don't use globals %pure_parser /* ===================== tokens ============================ */ /* tokens that have many lexical spellings */ %token TOK_NAME %token TOK_INTLIT %token TOK_EMBEDDED_CODE /* punctuators */ %token TOK_LBRACE "{" %token TOK_RBRACE "}" %token TOK_SEMICOLON ";" %token TOK_ARROW "->" %token TOK_LPAREN "(" %token TOK_RPAREN ")" %token TOK_LANGLE "<" %token TOK_RANGLE ">" %token TOK_STAR "*" %token TOK_AMPERSAND "&" %token TOK_COMMA "," %token TOK_EQUALS "=" %token TOK_COLON ":" /* keywords */ %token TOK_CLASS "class" %token TOK_PUBLIC "public" %token TOK_PRIVATE "private" %token TOK_PROTECTED "protected" %token TOK_VERBATIM "verbatim" %token TOK_IMPL_VERBATIM "impl_verbatim" %token TOK_CTOR "ctor" %token TOK_DTOR "dtor" %token TOK_PURE_VIRTUAL "pure_virtual" %token TOK_CUSTOM "custom" %token TOK_OPTION "option" %token TOK_NEW "new" %token TOK_ENUM "enum" /* ======================== types ========================== */ /* all pointers are interpreted as owner pointers */ %union { ASTSpecFile *file; ASTList *formList; TF_class *tfClass; ASTList *ctorArgList; ASTList *userDeclList; string *str; enum AccessCtl accessCtl; AccessMod *accessMod; ToplevelForm *verbatim; Annotation *annotation; TF_option *tfOption; ASTList *stringList; TF_enum *tfEnum; ASTList *enumeratorList; string *enumerator; ASTList *baseClassList; BaseClass *baseClass; CustomCode *customCode; } %type StartSymbol %type Input %type Class ClassBody ClassMembersOpt %type CtorArgsOpt CtorArgs CtorArgList %type CtorMembersOpt %type Arg ArgWord Embedded ArgList %type Public %type AccessMod %type Verbatim %type Annotation %type Option %type StringList OptionArgs %type Enum %type EnumeratorSeq %type Enumerator %type BaseClassesOpt BaseClassSeq %type BaseAccess %type BaseClass %type CustomCode; /* ===================== productions ======================= */ %% /* start symbol */ /* yields ASTSpecFile, though really $$ isn't used.. */ StartSymbol: Input { $$ = *((ASTSpecFile**)parseParam) = new ASTSpecFile($1); } ; /* sequence of toplevel forms */ /* yields ASTList */ Input: /* empty */ { $$ = new ASTList; } | Input Class { ($$=$1)->append($2); } | Input Verbatim { ($$=$1)->append($2); } | Input Option { ($$=$1)->append($2); } | Input Enum { ($$=$1)->append($2); } | Input CustomCode { ($$=$1)->append(new TF_custom($2)); } | Input ";" { $$=$1; } /* ignore extraneous semis */ ; /* a class is a nonterminal in the abstract grammar */ /* yields TF_class */ Class: NewOpt "class" TOK_NAME CtorArgsOpt BaseClassesOpt ClassBody { ($$=$6)->super->name = unbox($3); $$->super->args.steal($4); $$->super->bases.steal($5); } | NewOpt "class" TOK_NAME CtorArgs CtorArgs BaseClassesOpt ClassBody { ($$=$7)->super->name = unbox($3); $$->super->args.steal($4); $$->super->lastArgs.steal($5); $$->super->bases.steal($6); } ; /* for now, just allow "new" but don't interpret it */ NewOpt: /* empty */ {} | "new" {} ; /* * I contemplated making both kinds of forms end in semicolon, but then * realized that for consistency I should also put semis after the * inner ctor bodies, which I didn't want to do. So, I'll stick with the * general schema that entities are followed either by brace-delimited * bodies or a single ";". I can always put extensions inside the braces, * so the lack of syntax after "}" won't be a problem later. */ /* yields TF_class */ ClassBody: "{" ClassMembersOpt "}" /* no ";", see above */ { $$=$2; } | ";" { $$ = new TF_class(new ASTClass("(placeholder)", NULL, NULL, NULL, NULL), NULL); } ; /* yields TF_class */ /* does this by making an empty one initially, and then adding to it */ ClassMembersOpt : /* empty */ { $$ = new TF_class(new ASTClass("(placeholder)", NULL, NULL, NULL, NULL), NULL); } | ClassMembersOpt "->" TOK_NAME CtorArgsOpt BaseClassesOpt ";" { ($$=$1)->ctors.append(new ASTClass(unbox($3), $4, NULL, $5, NULL)); } | ClassMembersOpt "->" TOK_NAME CtorArgsOpt BaseClassesOpt "{" CtorMembersOpt "}" { ($$=$1)->ctors.append(new ASTClass(unbox($3), $4, NULL, $5, $7)); } | ClassMembersOpt Annotation { ($$=$1)->super->decls.append($2); } ; /* empty ctor args can have parens or not, at user's discretion */ /* yields ASTList */ CtorArgsOpt : /* empty */ { $$ = new ASTList; } | CtorArgs { $$ = $1; } ; /* yields ASTList */ CtorArgs : "(" ")" { $$ = new ASTList; } | "(" CtorArgList ")" { $$ = $2; } ; /* yields ASTList */ CtorArgList: Arg { $$ = new ASTList; { string tmp = unbox($1); $$->append(parseCtorArg(tmp)); } } | CtorArgList "," Arg { ($$=$1)->append(parseCtorArg(unbox($3))); } ; /* yields string */ Arg: ArgWord { $$ = $1; } | Arg ArgWord { $$ = appendStr($1, $2); } // dealloc's $1, $2 ; /* yields string */ ArgWord : TOK_NAME { $$ = appendStr($1, box(" ")); } | TOK_INTLIT { $$ = appendStr($1, box(" ")); } | "<" ArgList ">" { $$ = appendStr(box("<"), appendStr($2, box(">"))); } | "*" { $$ = box("*"); } | "&" { $$ = box("&"); } | "=" { $$ = box("="); } | TOK_CLASS { $$ = box("class "); } /* special b/c is ast spec keyword */ ; /* yields string, and may have commas inside */ ArgList: Arg { $$ = $1; } | Arg "," ArgList { $$ = appendStr($1, appendStr(box(","), $3)); } ; /* yields ASTList */ CtorMembersOpt : /* empty */ { $$ = new ASTList; } | CtorMembersOpt Annotation { ($$=$1)->append($2); } ; /* yields Annotation */ Annotation : AccessMod Embedded { $$ = new UserDecl($1, unbox($2), ""); } | AccessMod TOK_EMBEDDED_CODE "=" TOK_EMBEDDED_CODE ";" { $$ = new UserDecl($1, unbox($2), unbox($4)); } | CustomCode { $$ = $1; } ; /* yields CustomCode */ CustomCode : "custom" TOK_NAME Embedded { $$ = new CustomCode(unbox($2), unbox($3)); } ; /* yields string */ Embedded : TOK_EMBEDDED_CODE ";" { $$ = $1; } | "{" TOK_EMBEDDED_CODE "}" { $$ = $2; } ; /* yields AccessCtl */ Public : "public" { $$ = AC_PUBLIC; } | "private" { $$ = AC_PRIVATE; } | "protected" { $$ = AC_PROTECTED; } | "ctor" { $$ = AC_CTOR; } | "dtor" { $$ = AC_DTOR; } | "pure_virtual" { $$ = AC_PUREVIRT; } ; /* yield AccessMod */ AccessMod: Public { $$ = new AccessMod($1, NULL); } | Public "(" StringList ")" { $$ = new AccessMod($1, $3); } ; /* yield ASTList */ StringList: TOK_NAME { $$ = new ASTList($1); } | StringList "," TOK_NAME { ($$=$1)->append($3); } ; /* yields TF_verbatim */ Verbatim: "verbatim" Embedded { $$ = new TF_verbatim(unbox($2)); } | "impl_verbatim" Embedded { $$ = new TF_impl_verbatim(unbox($2)); } ; /* yields TF_option */ Option: "option" TOK_NAME OptionArgs ";" { $$ = new TF_option(unbox($2), $3); } ; /* yields ASTList */ OptionArgs: /*empty*/ { $$ = new ASTList; } | OptionArgs TOK_NAME { ($$=$1)->append($2); } ; /* yields TF_enum */ Enum: "enum" TOK_NAME "{" EnumeratorSeq "}" { $$ = new TF_enum(unbox($2), $4); } | "enum" TOK_NAME "{" EnumeratorSeq "," "}" { $$ = new TF_enum(unbox($2), $4); } ; /* yields ASTList */ EnumeratorSeq: Enumerator { $$ = new ASTList($1); } | EnumeratorSeq "," Enumerator { ($$=$1)->append($3); } ; /* yields string */ Enumerator: TOK_NAME { $$ = $1; } ; /* yields ASTList */ BaseClassesOpt: /* empty */ { $$ = new ASTList; } | ":" BaseClassSeq { $$ = $2; } ; /* yields ASTList */ BaseClassSeq: BaseClass { $$ = new ASTList($1); } | BaseClassSeq "," BaseClass { ($$=$1)->append($3); } ; /* yields AccessCtl */ BaseAccess : "public" { $$ = AC_PUBLIC; } | "private" { $$ = AC_PRIVATE; } | "protected" { $$ = AC_PROTECTED; } ; /* yields BaseClass */ BaseClass: BaseAccess TOK_NAME { $$ = new BaseClass($1, unbox($2)); } ; %% /* ----------------- extra C code ------------------- */