%{ /////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2000-2019 Ericsson Telecom AB // // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v2.0 // which accompanies this distribution, and is available at // https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html /////////////////////////////////////////////////////////////////////////////// // // File: SDP_parser.y // Rev: R14C // Prodnr: CNL 113 353 // Contact: http://ttcn.ericsson.se // Reference: ITU-T SDP /*C declarations*/ #include "SDP_parse_parser.h" #include #define YYDEBUG 1 using namespace SDP__Types; extern int SDP_parse_lex(); extern int SDP_parse_error(char *s); SDP__Message* SDP_parse_parsed_message; SDP__Message* SDP_parse_get_parsed_message() { return SDP_parse_parsed_message; } void SDP_parse_set_parsed_message(SDP__Message* pdu) { SDP_parse_parsed_message=pdu; } %} /*Bison declarations*/ %union { int number; INTEGER* intnum; char byte; CHARSTRING* t_charstring; SDP__Types::SDP__Message* t_sdp_message; SDP__Types::SDP__Origin* t_sdp_origin; SDP__Types::SDP__contact* t_sdp_contact; SDP__Types::SDP__email__list* t_sdp_email_list; SDP__Types::SDP__phone__list* t_sdp_phone_list; SDP__Types::SDP__connection* t_sdp_connection; SDP__Types::SDP__connection__list* t_sdp_connection_list; SDP__Types::SDP__conn__addr* t_sdp_conn_addr; SDP__Types::SDP__bandwidth* t_sdp_bandwidth; SDP__Types::SDP__time__list* t_sdp_time_list; SDP__Types::SDP__time* t_sdp_time; SDP__Types::SDP__time__field* t_sdp_time_field; SDP__Types::SDP__repeat* t_sdp_repeat; SDP__Types::SDP__repeat__list* t_sdp_repeat_list; SDP__Types::SDP__timezone__list* t_sdp_timezone_list; SDP__Types::SDP__timezone* t_sdp_timezone; SDP__Types::SDP__typed__time* t_sdp_typed_time; SDP__Types::SDP__typed__time__list* t_sdp_typed_time_list; SDP__Types::SDP__key* t_sdp_key; SDP__Types::SDP__attribute* t_sdp_attribute; SDP__Types::SDP__attribute__list* t_sdp_attribute_list; SDP__Types::SDP__media__desc* t_sdp_media_desc; SDP__Types::SDP__media__desc__list* t_sdp_media_desc_list; SDP__Types::SDP__media__field* t_sdp_media_field; SDP__Types::SDP__fmt__list* t_sdp_fmt_list; SDP__Types::SDP__bandwidth__list* t_bandwidth_list; SDP__Types::SDP__url__list* t_url_list; SDP__Types::SDP__media__type__list* t_type_list; SDP__Types::SDP__id__tag__list* t_id_list; SDP__Types::SDP__Remote__candidate__list* t_candidate_list; SDP__Types::SDP__Remote__candidate* t_candidate; SDP__Types::SDP__extension__list* t_extension_list; SDP__Types::SDP__extension* t_extension; SDP__Types::SDP__ice__options__list* t_sdp_ice_option_list; } %type announcement %type bandwidth_list %type media_descriptions %type url_list %type id_list %type type_list %type fmt_list %type media_field %type media_description %type attribute_fields %type attribute_field attribute %type key_field key_type %type time_list %type time %type time_field %type repeat %type repeat_list %type timezone_list timezones_field %type timezone %type typed_time %type offsets %type origin_field %type session_name_field information_field uri_field email_text phone transport %type candidate_list %type candidate %type extension_list %type extension %type ice_option_list %type email_fields %type phone_fields %type email_field email_address phone_field phone_number %type connection_field connection_field_lonely %type connection_fields %type conn_address %type bandwidth_field %type pos_digit digit proto_version %type alpha_numeric email_byte %token _ZERO _ONE _TWO _THREE _FOUR _FIVE _SIX _SEVEN _EIGHT _NINE %token CRLF %token ALPHA SPACE UNDERSCORE PERIOD ANYBYTE LBRACE RBRACE LT GT PLUS HYPHEN SLASH COLON %token EMAIL TOKEN %type rel_addr rel_port %token INTTOKEN %token VEQ OEQ SEQ IEQ UEQ EEQ PEQ CEQ BEQ BW_CT BW_AS TEQ ZEQ REQ KEQ AEQ MEQ %token A_CAT A_KEYWDS A_TOOL A_PTIME A_RECVONLY A_SENDRECV A_SENDONLY A_ORIENT A_TYPE A_CHARSET A_SDLANG %token A_LANG A_FRAMERATE A_QUALITY A_FMTP A_CURR A_DES A_CONF A_RTMAP A_RTCP A_MAX_SIZE A_PATH A_ACCEPT_TYPES %token A_ACCEPT_WRAPPED_TYPES A_MAXPRATE A_MID A_GROUP A_FILE_SELECTOR A_FILE_TRANSFER_ID A_INACTIVE A_SETUP %token A_CONNECTION A_CRYPTO A_CONTENT A_LABEL A_FLOORCTRL A_CONFID A_USERID A_FLOORID A_FINGERPRINT %token A_ICE_UFRAG A_ICE_PWD A_CANDIDATE A_ICE_LITE A_ICE_MISMATCH A_REMOTE_CANDIDATE A_ICE_OPTIONS %token A_RTCP_FB A_MAXPTIME %token A_T38_VERSION A_T38_BITRATE A_T38_BITREMOVAL A_T38_MMR A_T38_JBIG A_T38_RATEMANAGEMENT %token A_T38_MAXBUFFER A_T38_MAXDATAGRAM A_T38_IFP A_T38_EC A_T38_ECDEPTH A_T38_FEC A_T38_VENDORINFO %token A_T38_MODEM %token A_FILE_DISPOSITION A_FILE_DATE A_FILE_ICON A_FILE_RANGE %token A_SCTPMAP A_SCTPPORT A_MAX_MSG_SIZE A_RTCP_MUX %start announcement %% /*Grammar rules*/ announcement: proto_version origin_field session_name_field information_field uri_field email_fields phone_fields connection_field_lonely bandwidth_list time_list timezones_field key_field attribute_fields media_descriptions { // SDP_parse_parsed_message = new SDP__Message; (*SDP_parse_parsed_message).protocol__version() = $1; (*SDP_parse_parsed_message).origin() = *$2; delete $2; (*SDP_parse_parsed_message).session__name() = *$3; delete $3; if ($4 != NULL) { // information field present (*SDP_parse_parsed_message).information() = *$4; delete $4; } else (*SDP_parse_parsed_message).information() = OMIT_VALUE; if ($5 != NULL) { // uri field present (*SDP_parse_parsed_message).uri() = *$5; delete $5; } else (*SDP_parse_parsed_message).uri() = OMIT_VALUE; if ($6 != NULL) { //email fields present (*SDP_parse_parsed_message).emails() = *$6; delete $6; } else (*SDP_parse_parsed_message).emails() = OMIT_VALUE; if ($7 != NULL) { // phone fields present (*SDP_parse_parsed_message).phone__numbers() = *$7; delete $7; } else (*SDP_parse_parsed_message).phone__numbers() = OMIT_VALUE; if ($8 != NULL) { // connection fields present (*SDP_parse_parsed_message).connection() = (*$8); delete $8; } else (*SDP_parse_parsed_message).connection() = OMIT_VALUE; if ($9 != NULL) { (*SDP_parse_parsed_message).bandwidth() = *$9; delete $9; } else (*SDP_parse_parsed_message).bandwidth() = OMIT_VALUE; (*SDP_parse_parsed_message).times() = *$10; delete $10; if ($11 != NULL) { (*SDP_parse_parsed_message).timezone__adjustments() = *$11; delete $11; } else (*SDP_parse_parsed_message).timezone__adjustments() = OMIT_VALUE; if ($12 != NULL) { (*SDP_parse_parsed_message).key () = *$12; delete $12; } else { (*SDP_parse_parsed_message).key() = OMIT_VALUE; } if ($13 != NULL) { (*SDP_parse_parsed_message).attributes() = *$13; delete $13; } else { (*SDP_parse_parsed_message).attributes() = OMIT_VALUE; } if ($14 != NULL) { (*SDP_parse_parsed_message).media__list() = *$14; delete $14; } else (*SDP_parse_parsed_message).media__list() = OMIT_VALUE; YYACCEPT; } media_descriptions: /*empty*/ {$$ = NULL;} | media_descriptions media_description { if ($1 != NULL) { int media_num = (*$1).size_of(); (*$1)[media_num] = *$2; delete $2; } else { $$ = new SDP__media__desc__list(); (*$$)[0] = *$2; delete $2; } } media_description: media_field information_field connection_fields bandwidth_list key_field attribute_fields { $$ = new SDP__media__desc(); (*$$).media__field() = *$1; delete $1; if ($2 != NULL) { (*$$).information() = *$2; delete $2; } else (*$$).information() = OMIT_VALUE; if ($3 != NULL) { (*$$).connections() = *$3; delete $3; } else (*$$).connections() = OMIT_VALUE; if ($4 != NULL) { (*$$).bandwidth() = *$4; delete $4; } else (*$$).bandwidth() = OMIT_VALUE; if ($5 != NULL) { (*$$).key() = *$5; delete $5; } else (*$$).key() = OMIT_VALUE; if ($6 != NULL) { (*$$).attributes() = *$6; delete $6; } else (*$$).attributes()= OMIT_VALUE; } media_field: MEQ TOKEN SPACE TOKEN SLASH TOKEN SPACE transport SPACE fmt_list CRLF { $$ = new SDP__media__field(); (*$$).media() = *$2; delete $2; (*$$).ports().port__number() = str2int(*$4); delete $4; (*$$).ports().num__of__ports() = str2int(*$6); delete $6; (*$$).transport() = *$8; delete $8; (*$$).fmts() = *$10; delete $10; } | MEQ TOKEN SPACE TOKEN SPACE transport SPACE fmt_list CRLF { $$ = new SDP__media__field(); (*$$).media() = *$2; delete $2; (*$$).ports().port__number() = str2int(*$4); delete $4; (*$$).ports().num__of__ports() = OMIT_VALUE; (*$$).transport() = *$6; delete $6; (*$$).fmts() = *$8; delete $8; } transport: TOKEN { $$=$1;} | transport SLASH TOKEN { const CHARSTRING& str = *$1+CHARSTRING(1,"/")+*$3; delete $1; delete $3; $$ = new CHARSTRING(str); } fmt_list: TOKEN { $$ = new SDP__fmt__list(); (*$$)[0] = *$1; delete $1; } | fmt_list SPACE TOKEN { int fmt_num = (*$1).size_of(); (*$1)[fmt_num] = *$3; delete $3; $$ = $1; } attribute_fields: /*empty*/ { $$ = NULL; } | attribute_fields attribute_field { if ($1 != NULL) { int att_num = (*$1).size_of(); (*$1)[att_num] = *$2; delete $2; } else { $$ = new SDP__attribute__list(); (*$$)[0] = *$2; delete $2; } } attribute_field: AEQ attribute CRLF { $$ = $2; } attribute: A_CAT TOKEN { $$ = new SDP__attribute(); (*$$).cat().attr__value() = *$2; delete $2; } | A_KEYWDS TOKEN { $$ = new SDP__attribute(); (*$$).keywds().attr__value() = *$2; delete $2; } | A_TOOL TOKEN { $$ = new SDP__attribute(); (*$$).tool().attr__value() = *$2; delete $2; } | A_PTIME TOKEN { $$ = new SDP__attribute(); (*$$).ptime().attr__value() = *$2; delete $2; } | A_RECVONLY { $$ = new SDP__attribute(); (*$$).recvonly() = SDP__attribute__recvonly(NULL_VALUE); } | A_SENDRECV { $$ = new SDP__attribute(); (*$$).sendrecv() = SDP__attribute__sendrecv(NULL_VALUE); } | A_SENDONLY { $$ = new SDP__attribute(); (*$$).sendonly() = SDP__attribute__sendonly(NULL_VALUE); } | A_ORIENT TOKEN { $$ = new SDP__attribute(); (*$$).orient().attr__value() = *$2; delete $2; } | A_TYPE TOKEN { $$ = new SDP__attribute(); (*$$).sdp__type().attr__value() = *$2; delete $2; } | A_CHARSET TOKEN { $$ = new SDP__attribute(); (*$$).charset().attr__value() = *$2; delete $2; } | A_SDLANG TOKEN { $$ = new SDP__attribute(); (*$$).sdplang().attr__value() = *$2; delete $2; } | A_LANG TOKEN { $$ = new SDP__attribute(); (*$$).lang().attr__value() = *$2; delete $2; } | A_FRAMERATE TOKEN { $$ = new SDP__attribute(); (*$$).framerate().attr__value() = *$2; delete $2; } | A_QUALITY TOKEN { $$ = new SDP__attribute(); (*$$).quality().attr__value() = *$2; delete $2; } | A_FMTP TOKEN { $$ = new SDP__attribute(); (*$$).fmtp().attr__value() = *$2; delete $2; } | A_CURR TOKEN { $$ = new SDP__attribute(); (*$$).curr().attr__value() = *$2; delete $2; } | A_DES TOKEN { $$ = new SDP__attribute(); (*$$).des().attr__value() = *$2; delete $2; } | A_CONF TOKEN { $$ = new SDP__attribute(); (*$$).conf().attr__value() = *$2; delete $2; } | A_RTMAP TOKEN { $$ = new SDP__attribute(); (*$$).rtpmap().attr__value() = *$2; delete $2; } | A_RTCP TOKEN { $$ = new SDP__attribute(); (*$$).rtcp().attr__value() = *$2; delete $2; } | A_MAX_SIZE TOKEN { $$ = new SDP__attribute(); (*$$).max__size().max__size() = str2int(*$2); delete $2; } | A_PATH url_list { $$ = new SDP__attribute(); (*$$).path().path__list() = *$2; delete $2; } | A_ACCEPT_TYPES type_list { $$ = new SDP__attribute(); (*$$).accept__types().attr__value() = *$2; delete $2; } | A_ACCEPT_WRAPPED_TYPES type_list { $$ = new SDP__attribute(); (*$$).accept__wrapped__types().attr__value() = *$2; delete $2; } | A_MAXPRATE TOKEN { $$ = new SDP__attribute(); (*$$).maxprate().prate__integer__part() = str2int(*$2); (*$$).maxprate().prate__fraction__part() = OMIT_VALUE; delete $2; } | A_MAXPRATE TOKEN PERIOD TOKEN{ $$ = new SDP__attribute(); (*$$).maxprate().prate__integer__part() = str2int(*$2); (*$$).maxprate().prate__fraction__part() = str2int(*$4); delete $2; delete $4; } | A_MID TOKEN { $$ = new SDP__attribute(); (*$$).mid().id__tag() = *$2; delete $2; } | A_GROUP TOKEN { $$ = new SDP__attribute(); (*$$).group__attr().semantics() = *$2; (*$$).group__attr().id__tag()=OMIT_VALUE; delete $2; } | A_GROUP TOKEN SPACE id_list{ $$ = new SDP__attribute(); (*$$).group__attr().semantics() = *$2; (*$$).group__attr().id__tag()=*$4; delete $2; delete $4; } | A_FILE_SELECTOR TOKEN { $$ = new SDP__attribute(); (*$$).file__selector().attr__value() = *$2; delete $2; } | A_FILE_TRANSFER_ID TOKEN { $$ = new SDP__attribute(); (*$$).file__transfer__id().attr__value() = *$2; delete $2; } | A_INACTIVE{ $$ = new SDP__attribute(); (*$$).inactive() = SDP__attribute__inactive(NULL_VALUE); } | A_RTCP_MUX{ $$ = new SDP__attribute(); (*$$).rtcp__mux() = SDP__attribute__rtcp__mux(NULL_VALUE); } | A_SETUP TOKEN { $$ = new SDP__attribute(); (*$$).setup().attr__value() = *$2; delete $2; } | A_CONNECTION TOKEN { $$ = new SDP__attribute(); (*$$).connection().attr__value() = *$2; delete $2; } | A_CRYPTO TOKEN { $$ = new SDP__attribute(); (*$$).crypto().attr__value() = *$2; delete $2; } | A_CONTENT TOKEN { $$ = new SDP__attribute(); (*$$).content().attr__value() = *$2; delete $2; } | A_LABEL TOKEN { $$ = new SDP__attribute(); (*$$).attr__label().attr__value() = *$2; delete $2; } | A_FLOORCTRL TOKEN { $$ = new SDP__attribute(); (*$$).floorctrl().attr__value() = *$2; delete $2; } | A_CONFID TOKEN { $$ = new SDP__attribute(); (*$$).confid().attr__value() = *$2; delete $2; } | A_USERID TOKEN { $$ = new SDP__attribute(); (*$$).userid().attr__value() = *$2; delete $2; } | A_FLOORID TOKEN { $$ = new SDP__attribute(); (*$$).floorid().attr__value() = *$2; delete $2; } | A_FINGERPRINT TOKEN { $$ = new SDP__attribute(); (*$$).fingerprint().attr__value() = *$2; delete $2; } | A_ICE_UFRAG TOKEN { $$ = new SDP__attribute(); (*$$).ice__ufrag().attr__value() = *$2; delete $2; } | A_ICE_PWD TOKEN { $$ = new SDP__attribute(); (*$$).ice__pwd().attr__value() = *$2; delete $2; } | A_CANDIDATE TOKEN SPACE TOKEN SPACE TOKEN SPACE TOKEN SPACE TOKEN SPACE TOKEN SPACE TOKEN SPACE TOKEN rel_addr rel_port extension_list{ $$ = new SDP__attribute(); (*$$).candidate().foundation() = *$2; delete $2; (*$$).candidate().component__id() = str2int(*$4); delete $4; (*$$).candidate().transport() = *$6; delete $6; (*$$).candidate().priority() = str2int(*$8); delete $8; (*$$).candidate().connection__address() = *$10; delete $10; (*$$).candidate().connection__port() = str2int(*$12); delete $12; delete $14; (*$$).candidate().candidate__type() = *$16; delete $16; if ($17 != NULL) { (*$$).candidate().rel__address() = *$17; delete $17; } else (*$$).candidate().rel__address() = OMIT_VALUE; if ($18 != NULL) { (*$$).candidate().rel__port() = *$18; delete $18; } else (*$$).candidate().rel__port() = OMIT_VALUE; if ($19 != NULL) { (*$$).candidate().extensions() = *$19; delete $19; } else (*$$).candidate().extensions() = OMIT_VALUE; } | A_ICE_LITE { $$ = new SDP__attribute(); (*$$).ice__lite() = SDP__attribute__ice__lite(NULL_VALUE); } | A_ICE_MISMATCH { $$ = new SDP__attribute(); (*$$).ice__mismatch() = SDP__attribute__ice__mismatch(NULL_VALUE); } | A_REMOTE_CANDIDATE candidate_list { $$ = new SDP__attribute(); (*$$).remote__candidate().attr__value() = *$2; delete $2; } | A_ICE_OPTIONS ice_option_list { $$ = new SDP__attribute(); (*$$).ice__options().attr__value() = *$2; delete $2; } | A_RTCP_FB TOKEN { $$ = new SDP__attribute(); (*$$).rtcp__fb().attr__value() = *$2; delete $2; } | A_MAXPTIME TOKEN { $$ = new SDP__attribute(); (*$$).maxptime().attr__value() = *$2; delete $2; } | A_T38_VERSION TOKEN { $$ = new SDP__attribute(); (*$$).t38__version().attr__value() = str2int(*$2); delete $2; } | A_T38_BITRATE TOKEN { $$ = new SDP__attribute(); (*$$).t38__bit__rate().attr__value() = str2int(*$2); delete $2; } | A_T38_BITREMOVAL TOKEN { $$ = new SDP__attribute(); (*$$).t38__fill__bit__removal().attr__value() = str2int(*$2); delete $2; } | A_T38_MMR TOKEN { $$ = new SDP__attribute(); (*$$).t38__transcoding__mmr().attr__value() = str2int(*$2); delete $2; } | A_T38_JBIG TOKEN { $$ = new SDP__attribute(); (*$$).t38__transcoding__jbig().attr__value() = str2int(*$2); delete $2; } | A_T38_RATEMANAGEMENT TOKEN { $$ = new SDP__attribute(); (*$$).t38__rate__management().attr__value() = *$2; delete $2; } | A_T38_MAXBUFFER TOKEN { $$ = new SDP__attribute(); (*$$).t38__max__buffer().attr__value() = str2int(*$2); delete $2; } | A_T38_MAXDATAGRAM TOKEN { $$ = new SDP__attribute(); (*$$).t38__max__datagram().attr__value() = str2int(*$2); delete $2; } | A_T38_IFP TOKEN { $$ = new SDP__attribute(); (*$$).t38__max__ifp().attr__value() = str2int(*$2); delete $2; } | A_T38_EC TOKEN { $$ = new SDP__attribute(); (*$$).t38__udp__ec().attr__value() = *$2; delete $2; } | A_T38_ECDEPTH TOKEN { $$ = new SDP__attribute(); (*$$).t38__udp__ec__depth().minred() = str2int(*$2); (*$$).t38__udp__ec__depth().maxred() = OMIT_VALUE; delete $2; } | A_T38_ECDEPTH TOKEN SPACE TOKEN { $$ = new SDP__attribute(); (*$$).t38__udp__ec__depth().minred() = str2int(*$2); (*$$).t38__udp__ec__depth().maxred() = str2int(*$4); delete $2; delete $4; } | A_T38_FEC TOKEN { $$ = new SDP__attribute(); (*$$).t38__udp__fec__max__spam().attr__value() = str2int(*$2); delete $2; } | A_T38_VENDORINFO TOKEN SPACE TOKEN SPACE TOKEN { $$ = new SDP__attribute(); (*$$).t38__vendor__info().t35country__code() = str2int(*$2); (*$$).t38__vendor__info().t35extension() = str2int(*$4); (*$$).t38__vendor__info().manufacturer__code() = str2int(*$6); delete $2; delete $4; delete $6; } | A_T38_MODEM TOKEN { $$ = new SDP__attribute(); (*$$).t38__modem__type().attr__value() = *$2; delete $2; } | A_FILE_DISPOSITION TOKEN { $$ = new SDP__attribute(); (*$$).file__disposition().attr__value() = *$2; delete $2; } | A_FILE_DATE TOKEN { $$ = new SDP__attribute(); (*$$).file__date().attr__value() = *$2; delete $2; } | A_FILE_ICON TOKEN { $$ = new SDP__attribute(); (*$$).file__icon().attr__value() = *$2; delete $2; } | A_FILE_RANGE TOKEN { $$ = new SDP__attribute(); (*$$).file__range().attr__value() = *$2; delete $2; } | A_SCTPMAP TOKEN { $$ = new SDP__attribute(); (*$$).sctpmap().attr__value() = *$2; delete $2; } | A_SCTPPORT TOKEN { $$ = new SDP__attribute(); (*$$).sctp__port().attr__value() = str2int(*$2); delete $2; } | A_MAX_MSG_SIZE TOKEN { $$ = new SDP__attribute(); (*$$).max__message__size().attr__value() = str2int(*$2); delete $2; } | TOKEN COLON TOKEN { $$ = new SDP__attribute(); (*$$).unknown().name() = *$1; delete $1; (*$$).unknown().attr__value() = *$3; delete $3; } | TOKEN { $$ = new SDP__attribute(); (*$$).unknown().name() = *$1; delete $1; (*$$).unknown().attr__value() = OMIT_VALUE; } ice_option_list: TOKEN { $$ = new SDP__ice__options__list(); (*$$)[0] = *$1; delete $1; } | ice_option_list SPACE TOKEN { int ice_option_num = (*$1).size_of(); (*$1)[ice_option_num] = *$3; delete $3; $$ = $1; } candidate_list: candidate { $$ = new SDP__Remote__candidate__list(); (*$$)[0] = *$1; delete $1; } | candidate_list SPACE candidate { int candidate_num = (*$1).size_of(); (*$1)[candidate_num] = *$3; delete $3; $$ = $1; } candidate: TOKEN SPACE TOKEN SPACE TOKEN{ $$ = new SDP__Remote__candidate(); (*$$).component__Id() = *$1; delete $1; (*$$).connection__address() = *$3; delete $3; (*$$).portValue() = str2int(*$5); delete $5; } rel_addr: /*empty*/ {$$ = NULL;} | SPACE TOKEN SPACE TOKEN{ delete $2; $$ = $4; } rel_port: /*empty*/ {$$ = NULL;} | SPACE TOKEN SPACE TOKEN{ delete $2; $$ = $4; } extension_list: /*empty*/ {$$ = NULL;} | extension_list extension { if ($1 != NULL) { int extension_num = (*$1).size_of(); (*$1)[extension_num] = *$2; delete $2; $$ = $1; } else { $$ = new SDP__extension__list(); (*$$)[0] = *$2; delete $2; } } extension: SPACE TOKEN SPACE TOKEN { $$ = new SDP__extension(); (*$$).extension__attr__name() = *$2; delete $2; (*$$).extension__attr__value() = *$4; delete $4; } url_list: TOKEN { $$ = new SDP__url__list(); (*$$)[0] = *$1; delete $1; } | url_list SPACE TOKEN { int url_num = (*$1).size_of(); (*$1)[url_num] = *$3; delete $3; $$ = $1; } id_list: TOKEN { $$ = new SDP__id__tag__list(); (*$$)[0] = *$1; delete $1; } | id_list SPACE TOKEN { int id_num = (*$1).size_of(); (*$1)[id_num] = *$3; delete $3; $$ = $1; } type_list: TOKEN { $$ = new SDP__media__type__list(); (*$$)[0] = *$1; delete $1; } | type_list SPACE TOKEN { int url_num = (*$1).size_of(); (*$1)[url_num] = *$3; delete $3; $$ = $1; } key_field: /*empty*/ {$$ = NULL;} | KEQ key_type CRLF { $$ = $2; } key_type: TOKEN { $$ = new SDP__key(); (*$$).method() = *$1; delete $1; (*$$).key() = OMIT_VALUE; } | TOKEN COLON TOKEN { $$ = new SDP__key(); (*$$).method() = *$1; delete $1; (*$$).key() = *$3; delete $3; } time_list: time { $$ = new SDP__time__list(); (*$$)[0] = *$1; delete $1; } | time_list time { int time_num = (*$1).size_of(); (*$1)[time_num] = *$2; delete $2; $$ = $1; } time: time_field repeat_list{ $$ = new SDP__time; (*$$).time__field() = *$1; delete $1; if ($2 != NULL) { (*$$).time__repeat() = *$2; delete $2; } else (*$$).time__repeat() = OMIT_VALUE; } repeat_list: /*empty*/ {$$ = NULL;} | repeat_list repeat { if ($1 != NULL) { int repeat_num = (*$1).size_of(); (*$1)[repeat_num] = *$2; delete $2; $$ = $1; } else { $$ = new SDP__repeat__list(); (*$$)[0] = *$2; delete $2; } } repeat: REQ typed_time SPACE typed_time SPACE offsets CRLF { $$ = new SDP__repeat(); (*$$).repeat__interval() = *$2; delete $2; (*$$).active() = *$4; delete $4; (*$$).offsets() = *$6; delete $6; } offsets: typed_time { $$ = new SDP__typed__time__list(); (*$$)[0] = *$1; delete $1; } | offsets SPACE typed_time { int off_size = (*$1).size_of(); (*$$)[off_size] = *$3; delete $3; } timezones_field: /*empty*/ {$$ = NULL;} | ZEQ timezone_list CRLF { $$ = $2; } timezone_list: timezone { $$ = new SDP__timezone__list(); (*$$)[0] = *$1; delete $1; } | timezone_list SPACE timezone { int tz_num = (*$1).size_of(); (*$1)[tz_num] = *$3; delete $3; $$ = $1; } timezone: INTTOKEN SPACE typed_time { $$ = new SDP__timezone(); (*$$).adjustment__time() = int2str(*$1); delete $1; (*$$).offset() = *$3; delete $3; } typed_time: INTTOKEN { $$ = new SDP__typed__time(); (*$$).time() = *$1; delete $1; (*$$).unit() = OMIT_VALUE; } | INTTOKEN ALPHA { $$ = new SDP__typed__time(); (*$$).time() = *$1; delete $1; (*$$).unit() = CHARSTRING(1, (const char*)&$2); } time_field: TEQ TOKEN SPACE TOKEN CRLF { // start_time SPACE stop_time $$ = new SDP__time__field(); (*$$).start__time() = (*$2); delete $2; (*$$).stop__time() = (*$4); delete $4; } bandwidth_list: /*empty*/ {$$ = NULL;} | bandwidth_list bandwidth_field { if ($1 != NULL) { int bandwidth_num = (*$1).size_of(); (*$1)[bandwidth_num] = *$2; delete $2; $$ = $1; } else { $$ = new SDP__bandwidth__list(); (*$$)[0] = *$2; delete $2; } } bandwidth_field: BEQ TOKEN COLON TOKEN CRLF { $$ = new SDP__bandwidth(); (*$$).modifier() = *$2; delete $2; (*$$).bandwidth() = str2int(*$4); delete $4; } connection_fields: /*empty*/ {$$ = NULL;} | connection_fields connection_field { if ($1 != NULL) { int con_num = (*$1).size_of(); (*$1)[con_num] = *$2; delete $2; $$ = $1; } else { $$ = new SDP__connection__list(); (*$$)[0] = *$2; delete $2; } } connection_field_lonely: /*empty*/ {$$ = NULL;} | CEQ TOKEN SPACE TOKEN SPACE conn_address CRLF { $$ = new SDP__connection(); (*$$).net__type() = *$2; delete $2; (*$$).addr__type() = *$4; delete $4; (*$$).conn__addr() = (*$6); delete $6; } connection_field: CEQ TOKEN SPACE TOKEN SPACE conn_address CRLF { $$ = new SDP__connection(); (*$$).net__type() = *$2; delete $2; (*$$).addr__type() = *$4; delete $4; (*$$).conn__addr() = (*$6); delete $6; } conn_address: TOKEN { $$ = new SDP__conn__addr(); (*$$).addr() = (*$1); delete $1; (*$$).ttl() = OMIT_VALUE; (*$$).num__of__addr() = OMIT_VALUE; } | TOKEN SLASH TOKEN { $$ = new SDP__conn__addr(); (*$$).addr() = (*$1); delete $1; (*$$).ttl() = str2int(*$3); (*$$).num__of__addr() = OMIT_VALUE; delete $3; } | TOKEN SLASH TOKEN SLASH TOKEN { $$ = new SDP__conn__addr(); (*$$).addr() = (*$1); delete $1; (*$$).ttl() = str2int(*$3); (*$$).num__of__addr() = str2int(*$5); delete $3; delete $5; } phone_fields: /*empty*/ {$$ = NULL;} | phone_fields phone_field { if ($$ == NULL) { $$ = new SDP__phone__list(); (*$$)[0] = *$2; delete $2; } else { int num_of_phonenumbers = (*$1).size_of(); (*$1)[num_of_phonenumbers] =*$2; delete $2; } } phone_field: PEQ phone_number CRLF { $$ = $2; } phone_number: phone { $$ = new SDP__contact(); (*$$).addr__or__phone() = (*$1); delete $1; (*$$).disp__name() = OMIT_VALUE; } | phone LBRACE email_text RBRACE { $$ = new SDP__contact(); (*$$).addr__or__phone() = *$1; delete $1; (*$$).disp__name() = *$3; delete $3; } | phone LT phone GT { /* phone is any charstring, but with trailing space removed*/ $$ = new SDP__contact(); (*$$).addr__or__phone() = *$3; delete $3; (*$$).disp__name() = *$1; delete $1; } phone: email_text { /* remove trailing space, if any */ /* This is a rather ugly post-processing, but otherwise SDP can not be parsed with an LR(1) parser. Reason: phone number may contain spaces, and delimiter between the phone number and the rest of the phone field may be a space*/ int size = (*$1).lengthof(); const char* buf = (const char*)(*$1); if (buf[size-1] == ' ') { $$ = new CHARSTRING(size-1, (const char*)(*$1)); delete $1; } else $$ = $1; } email_fields: /*empty*/ {$$ = NULL;} | email_fields email_field { if ($1 == NULL) { $$ = new SDP__email__list(); (*$$)[0] = *$2; delete $2; } else { int num_of_emails = (*$1).size_of(); // indexing begins with 0 (*$1)[num_of_emails] = *$2; delete $2; } } email_field: EEQ email_address CRLF { $$ = $2; } email_address: EMAIL { $$ = new SDP__contact(); (*$$).addr__or__phone() = *$1; delete $1; (*$$).disp__name() = OMIT_VALUE; } | EMAIL SPACE LBRACE email_text RBRACE { $$ = new SDP__contact(); (*$$).addr__or__phone() = *$1; delete $1; (*$$).disp__name() = *$4; delete $4; } | email_text SPACE LT EMAIL GT { $$ = new SDP__contact(); (*$$).addr__or__phone() = *$4; delete $4; (*$$).disp__name() = *$1; delete $1; } | LT EMAIL GT { $$ = new SDP__contact(); (*$$).addr__or__phone() = *$2; delete $2; (*$$).disp__name() = OMIT_VALUE; } uri_field: /*empty*/ {$$ = NULL;} | UEQ TOKEN CRLF { $$ = $2; } information_field: /*empty*/ {$$ = NULL;} | IEQ TOKEN CRLF { $$ = $2; } session_name_field: SEQ TOKEN CRLF { $$ = $2; } proto_version: VEQ INTTOKEN CRLF {$$ = *$2; delete $2;} origin_field: OEQ TOKEN SPACE TOKEN SPACE TOKEN SPACE TOKEN SPACE TOKEN SPACE TOKEN CRLF { $$ = new SDP__Origin(); (*$$).user__name() = *$2; delete $2; (*$$).session__id() = *$4; delete $4; (*$$).session__version() = *$6; delete $6; (*$$).net__type() = *$8; delete $8; (*$$).addr__type() = *$10; delete $10; (*$$).addr() = *$12; delete $12; } email_text: email_byte {$$ = new CHARSTRING(1, (const char*)&$1);} | email_text email_byte { const CHARSTRING& str = *$1 + CHARSTRING(1, (const char*)&$2); delete $1; $$ = new CHARSTRING(str); } alpha_numeric: ALPHA {$$ = $1;} | digit {$$ = $1 + 0x30;} digit: _ZERO {$$ = 0;} | pos_digit {$$ = $1;} pos_digit: _ONE {$$ = 1;} | _TWO {$$ = 2;} | _THREE {$$ = 3;} | _FOUR {$$ = 4;} | _FIVE {$$ = 5;} | _SIX {$$ = 6;} | _SEVEN {$$ = 7;} | _EIGHT {$$ = 8;} | _NINE {$$ = 9;} email_byte: alpha_numeric {$$ = $1;} | UNDERSCORE {$$ = $1;} | PERIOD {$$ = $1;} | HYPHEN {$$ = $1;} | PLUS {$$ = $1;} | SLASH {$$ = $1;} | COLON {$$ = $1;} | ANYBYTE {$$ = $1;} | SPACE {$$ = $1;} %% /*Additional C code*/