1 /* 2 * Grammar for a simple interface description language. 3 * 4 * Copyright (C) 2019, 2022 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 import *last_import = NULL; 37 struct include *last_include = NULL; 38 const char *output_dirname = NULL, *output_basename = NULL; 39 %} 40 41 %define parse.error verbose 42 43 /* Define the identifier type employed in the scanner. */ 44 45 %union { 46 long num; 47 char *str; 48 struct import imp; 49 struct include inc; 50 struct interface iface; 51 struct interface_ref iface_ref; 52 struct signature sig; 53 struct identifier ident; 54 struct parameter param; 55 struct attribute attr; 56 } 57 58 /* Associate identifiers and similar values with the string union member. */ 59 60 %type <str> IDENTIFIER DECIMAL HEXADECIMAL 61 %type <str> interface_name 62 %type <str> qualifier operation 63 %type <str> header PHEADER QHEADER 64 %type <str> attr_param 65 66 /* Specifiers and items have numeric values. */ 67 68 %type <num> IN INOUT OUT 69 %type <num> specifier 70 %type <num> CAP FPAGE 71 %type <num> item 72 73 /* Associate rules with the appropriate union members. */ 74 75 %type <imp> import 76 %type <inc> include 77 %type <iface> q_interface 78 %type <iface> interface 79 %type <iface_ref> interface_bases 80 %type <sig> q_signature 81 %type <sig> signature 82 %type <sig> signatures 83 %type <attr> attribute 84 %type <attr> attributes 85 %type <param> parameter 86 %type <param> parameters 87 %type <ident> attr_params 88 %type <ident> identifiers 89 90 /* Scanner token types. */ 91 92 %token IMPORT INCLUDE PHEADER QHEADER 93 %token INTERFACE 94 %token BEGINSECTION ENDSECTION 95 %token LPAR RPAR 96 %token LBRACE RBRACE 97 %token SEP TERM 98 %token IN INOUT OUT 99 %token CAP FPAGE 100 %token IDENTIFIER DECIMAL HEXADECIMAL 101 %token COMPOSES 102 103 /* Starting rule. */ 104 105 %start file 106 107 %% 108 109 /* Parse each file, with last_interface yielding the parsing products. */ 110 111 file : statements 112 ; 113 114 statements : statement statements 115 | %empty 116 ; 117 118 statement : import 119 | include 120 | q_interface 121 { $1.output_dirname = output_dirname; $1.output_basename = output_basename; 122 $1.tail = last_interface; last_interface = copy_interface($1); } 123 ; 124 125 import : IMPORT QHEADER TERM 126 { $$.filename = $2; $$.tail = last_import; last_import = copy_import($$); } 127 ; 128 129 include : INCLUDE header 130 { $$.filename = $2; $$.tail = last_include; last_include = copy_include($$); } 131 ; 132 133 header : PHEADER 134 | QHEADER 135 ; 136 137 /* Interface qualified with or without attributes, either having a signature 138 section or a list of base interfaces. */ 139 140 q_interface : LBRACE attributes RBRACE interface 141 { $4.attributes = copy_attribute($2); $$ = $4; } 142 | interface 143 { $$.attributes = NULL; } 144 ; 145 146 interface : INTERFACE interface_name BEGINSECTION signatures ENDSECTION TERM 147 { $$.name = $2; $$.bases = NULL; $$.signatures = copy_signature($4); 148 $$.imports = last_import; 149 $$.includes = last_include; last_include = NULL; } 150 | INTERFACE interface_name BEGINSECTION ENDSECTION TERM 151 { $$.name = $2; $$.bases = NULL; $$.signatures = NULL; 152 $$.imports = last_import; 153 $$.includes = last_include; last_include = NULL; } 154 | INTERFACE interface_name COMPOSES interface_bases TERM 155 { $$.name = $2; $$.bases = copy_interface_ref($4); $$.signatures = NULL; 156 $$.imports = last_import; 157 $$.includes = last_include; last_include = NULL; } 158 ; 159 160 interface_name : IDENTIFIER ; 161 162 interface_bases : interface_name SEP interface_bases 163 { $$.name = $1; $$.iface = NULL; copy_tail(interface_ref, $$, $3); } 164 | interface_name 165 { $$.name = $1; $$.iface = NULL; $$.tail = NULL; } 166 167 /* Signatures qualified with or without attributes. */ 168 169 signatures : q_signature signatures 170 { copy_tail(signature, $1, $2); $$ = $1; } 171 | q_signature 172 { $1.tail = NULL; $$ = $1; } 173 ; 174 175 q_signature : LBRACE attributes RBRACE signature 176 { $4.attributes = copy_attribute($2); $$ = $4; } 177 | signature 178 { $1.attributes = NULL; $$ = $1; } 179 ; 180 181 signature : qualifier operation LPAR RPAR TERM 182 { $$.qualifier = $1; $$.operation = $2; $$.parameters = NULL; } 183 | qualifier operation LPAR parameters RPAR TERM 184 { $$.qualifier = $1; $$.operation = $2; $$.parameters = copy_parameter($4); } 185 ; 186 187 qualifier : IDENTIFIER ; 188 189 operation : IDENTIFIER ; 190 191 /* Attributes with or without parameters. */ 192 193 attributes : attribute SEP attributes 194 { copy_tail(attribute, $1, $3); $$ = $1; } 195 | attribute 196 { $1.tail = NULL; $$ = $1; } 197 ; 198 199 attribute : IDENTIFIER LPAR attr_params RPAR 200 { $$.attribute = $1; $$.identifiers = copy_identifier($3); } 201 | IDENTIFIER 202 { $$.attribute = $1; $$.identifiers = NULL; } 203 ; 204 205 attr_params : attr_param SEP attr_params 206 { $$.identifier = $1; copy_tail(identifier, $$, $3); } 207 | attr_param 208 { $$.identifier = $1; $$.tail = NULL; } 209 ; 210 211 attr_param : IDENTIFIER 212 | DECIMAL 213 | HEXADECIMAL 214 ; 215 216 /* Signature parameters. */ 217 218 parameters : parameter SEP parameters 219 { copy_tail(parameter, $1, $3); $$ = $1; } 220 | parameter 221 { $1.tail = NULL; $$ = $1; } 222 ; 223 224 parameter : specifier item identifiers 225 { $$.specifier = $1; $$.cls = $2; $$.identifiers = copy_identifier($3); } 226 | specifier identifiers 227 { $$.specifier = $1; $$.cls = WORD_CLASS; $$.identifiers = copy_identifier($2); } 228 ; 229 230 specifier : IN | INOUT | OUT ; 231 232 item : CAP | FPAGE ; 233 234 identifiers : IDENTIFIER 235 { $$.identifier = $1; $$.tail = NULL; } 236 | IDENTIFIER identifiers 237 { $$.identifier = $1; copy_tail(identifier, $$, $2); } 238 ; 239 240 %% 241 242 void *copy(void *value) 243 { 244 union YYSTYPE *v; 245 246 if (value == NULL) 247 return value; 248 249 v = (union YYSTYPE *) malloc(sizeof(union YYSTYPE)); 250 memcpy(v, value, sizeof(union YYSTYPE)); 251 return v; 252 } 253 254 void reset(const char *dirname, const char *basename) 255 { 256 last_interface = NULL; 257 last_import = NULL; 258 last_include = NULL; 259 output_dirname = dirname; 260 output_basename = basename; 261 } 262 263 void yyerror(const char *message) 264 { 265 printf("%s\n", message); 266 }