1 /* 2 * Grammar for a simple interface description language. 3 * 4 * Copyright (C) 2019 Paul Boddie <paul@boddie.org.uk> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA 20 */ 21 22 %{ 23 #include <stdio.h> 24 #include <string.h> 25 #include "program.h" 26 #include "parser.h" 27 28 /* Standard signatures. */ 29 30 int yylex(void); 31 void yyerror(const char *); 32 33 /* State information, also reset by the function defined below. */ 34 35 struct interface *last_interface = NULL; 36 struct include *last_include = NULL; 37 %} 38 39 %define parse.error verbose 40 41 /* Define the identifier type employed in the scanner. */ 42 43 %union { 44 long num; 45 char *str; 46 struct include inc; 47 struct interface iface; 48 struct signature sig; 49 struct identifier ident; 50 struct parameter param; 51 struct attribute attr; 52 } 53 54 /* Associate identifiers and similar values with the string union member. */ 55 56 %type <str> IDENTIFIER DECIMAL HEXADECIMAL 57 %type <str> interface_name 58 %type <str> qualifier operation 59 %type <str> HEADER 60 %type <str> attr_param 61 62 /* Specifiers and items have numeric values. */ 63 64 %type <num> IN INOUT OUT 65 %type <num> specifier 66 %type <num> CAP FPAGE 67 %type <num> item 68 69 /* Associate rules with the appropriate union members. */ 70 71 %type <inc> include 72 %type <iface> q_interface 73 %type <iface> interface 74 %type <sig> q_signature 75 %type <sig> signature 76 %type <sig> signatures 77 %type <attr> attribute 78 %type <attr> attributes 79 %type <param> parameter 80 %type <param> parameters 81 %type <ident> attr_params 82 %type <ident> identifiers 83 84 /* Scanner token types. */ 85 86 %token INCLUDE HEADER 87 %token INTERFACE 88 %token BEGINSECTION ENDSECTION 89 %token LPAR RPAR 90 %token LBRACE RBRACE 91 %token SEP TERM 92 %token IN INOUT OUT 93 %token CAP FPAGE 94 %token IDENTIFIER DECIMAL HEXADECIMAL 95 96 /* Starting rule. */ 97 98 %start file 99 100 %% 101 102 file : statements 103 { write_files(last_interface); } 104 ; 105 106 statements : statement statements 107 | %empty 108 ; 109 110 statement : include 111 | q_interface 112 { $1.tail = last_interface; last_interface = copy_interface($1); } 113 ; 114 115 include : INCLUDE HEADER 116 { $$.filename = $2; $$.tail = last_include; last_include = copy_include($$); } 117 ; 118 119 /* Interface qualified with or without attributes. */ 120 121 q_interface : LBRACE attributes RBRACE interface 122 { $4.attributes = copy_attribute($2); $$ = $4; } 123 | interface 124 { $$.attributes = NULL; } 125 ; 126 127 interface : INTERFACE interface_name BEGINSECTION signatures ENDSECTION TERM 128 { $$.name = $2; $$.signatures = copy_signature($4); $$.includes = last_include; last_include = NULL; } 129 | INTERFACE interface_name BEGINSECTION ENDSECTION TERM 130 { $$.name = $2; $$.signatures = NULL; $$.includes = last_include; last_include = NULL; } 131 ; 132 133 interface_name : IDENTIFIER ; 134 135 /* Signatures qualified with or without attributes. */ 136 137 signatures : q_signature signatures 138 { copy_tail(signature, $1, $2); $$ = $1; } 139 | q_signature 140 { $1.tail = NULL; $$ = $1; } 141 ; 142 143 q_signature : LBRACE attributes RBRACE signature 144 { $4.attributes = copy_attribute($2); $$ = $4; } 145 | signature 146 { $1.attributes = NULL; $$ = $1; } 147 ; 148 149 signature : qualifier operation LPAR RPAR TERM 150 { $$.qualifier = $1; $$.operation = $2; $$.parameters = NULL; } 151 | qualifier operation LPAR parameters RPAR TERM 152 { $$.qualifier = $1; $$.operation = $2; $$.parameters = copy_parameter($4); } 153 ; 154 155 qualifier : IDENTIFIER ; 156 157 operation : IDENTIFIER ; 158 159 /* Attributes with or without parameters. */ 160 161 attributes : attribute SEP attributes 162 { copy_tail(attribute, $1, $3); $$ = $1; } 163 | attribute 164 { $1.tail = NULL; $$ = $1; } 165 ; 166 167 attribute : IDENTIFIER LPAR attr_params RPAR 168 { $$.attribute = $1; $$.identifiers = copy_identifier($3); } 169 | IDENTIFIER 170 { $$.attribute = $1; $$.identifiers = NULL; } 171 ; 172 173 attr_params : attr_param SEP attr_params 174 { $$.identifier = $1; copy_tail(identifier, $$, $3); } 175 | attr_param 176 { $$.identifier = $1; $$.tail = NULL; } 177 ; 178 179 attr_param : IDENTIFIER 180 | DECIMAL 181 | HEXADECIMAL 182 ; 183 184 /* Signature parameters. */ 185 186 parameters : parameter SEP parameters 187 { copy_tail(parameter, $1, $3); $$ = $1; } 188 | parameter 189 { $1.tail = NULL; $$ = $1; } 190 ; 191 192 parameter : specifier item identifiers 193 { $$.specifier = $1; $$.cls = $2; $$.identifiers = copy_identifier($3); } 194 | specifier identifiers 195 { $$.specifier = $1; $$.cls = WORD_CLASS; $$.identifiers = copy_identifier($2); } 196 ; 197 198 specifier : IN | INOUT | OUT ; 199 200 item : CAP | FPAGE ; 201 202 identifiers : IDENTIFIER 203 { $$.identifier = $1; $$.tail = NULL; } 204 | IDENTIFIER identifiers 205 { $$.identifier = $1; copy_tail(identifier, $$, $2); } 206 ; 207 208 %% 209 210 void *copy(void *value) 211 { 212 union YYSTYPE *v; 213 214 if (value == NULL) 215 return value; 216 217 v = (union YYSTYPE *) malloc(sizeof(union YYSTYPE)); 218 memcpy(v, value, sizeof(union YYSTYPE)); 219 return v; 220 } 221 222 void reset(void) 223 { 224 last_interface = NULL; 225 last_include = NULL; 226 } 227 228 void yyerror(const char *message) 229 { 230 printf("%s\n", message); 231 }