diff --git a/src/gram.c b/src/gram.c index 66f550cb..7a58cec3 100644 --- a/src/gram.c +++ b/src/gram.c @@ -44,6 +44,8 @@ int nvars = 0; symbol_number *token_translations = NULL; +enum braces_state prec_braces = 0; + int max_user_token_number = 256; bool diff --git a/src/gram.h b/src/gram.h index 52de2de2..50e442d0 100644 --- a/src/gram.h +++ b/src/gram.h @@ -117,6 +117,17 @@ typedef int item_number; extern item_number *ritem; extern unsigned int nritems; +enum braces_state + { + default_braces_state, + gprec_seen, + group_name_seen, + braces_seen + }; + +/* Marker for the lexer and parser, to correctly interpret braces. */ +extern enum braces_state prec_braces; + /* There is weird relationship between OT1H item_number and OTOH symbol_number and rule_number: we store the latter in item_number. symbol_number values are stored as-is, while diff --git a/src/parse-gram.y b/src/parse-gram.y index 1ec4b4dc..89af756b 100644 --- a/src/parse-gram.y +++ b/src/parse-gram.y @@ -130,6 +130,7 @@ %token PERCENT_PREC "%prec" %token PERCENT_DPREC "%dprec" +%token PERCENT_GPREC "%gprec" %token PERCENT_MERGE "%merge" /*----------------------. @@ -178,6 +179,8 @@ %token TAG "" %token TAG_ANY "<*>" %token TAG_NONE "<>" +%token LBRACE "{" +%token RBRACE "}" %union {unsigned char character;} %type CHAR @@ -214,6 +217,7 @@ %union {named_ref *named_ref;} %type named_ref.opt +%type prec_group_name.opt /*---------. | %param. | `---------*/ @@ -365,6 +369,7 @@ params: grammar_declaration: precedence_declaration +| precedence_group_declaration | symbol_declaration | "%start" symbol { @@ -457,6 +462,30 @@ symbol_declaration: } ; +/* A group of symbols for precedence declaration */ +precedence_group_declaration: + "%gprec" prec_group_name.opt + { + set_current_group ($2, &@2); + } + "{" precedence_declarations "}" + { + set_current_group (DEFAULT_GROUP_NAME, NULL); + } +; + +/* Name for the precedence group. If none is present a new unique one is + generated. */ +prec_group_name.opt: + %empty { $$ = new_anonymous_group_name (); } +| variable /* Just a string, maybe there's a better way? */ +; + +precedence_declarations: + precedence_declaration +| precedence_declarations precedence_declaration +; + precedence_declaration: precedence_declarator tag.opt symbols.prec { diff --git a/src/scan-gram.l b/src/scan-gram.l index 665e80de..f5157c95 100644 --- a/src/scan-gram.l +++ b/src/scan-gram.l @@ -223,6 +223,10 @@ eqopt ([[:space:]]*=)? "%fixed-output-files" return PERCENT_YACC; "%initial-action" return PERCENT_INITIAL_ACTION; "%glr-parser" return PERCENT_GLR_PARSER; + "%gprec" { + prec_braces = gprec_seen; + return PERCENT_GPREC; + } "%language" return PERCENT_LANGUAGE; "%left" return PERCENT_LEFT; "%lex-param" RETURN_PERCENT_PARAM(lex); @@ -273,10 +277,16 @@ eqopt ([[:space:]]*=)? "=" return EQUAL; "|" return PIPE; ";" return SEMICOLON; + "}" return RBRACE; {id} { val->uniqstr = uniqstr_new (yytext); id_loc = *loc; + if (prec_braces == gprec_seen) + { + prec_braces = group_name_seen; + return ID; + } bracketed_id_str = NULL; BEGIN SC_AFTER_IDENTIFIER; } @@ -307,6 +317,11 @@ eqopt ([[:space:]]*=)? /* Code in between braces. */ "{" { + if (prec_braces == gprec_seen || prec_braces == group_name_seen) + { + prec_braces = braces_seen; + return LBRACE; + } STRING_GROW; nesting = 0; code_start = loc->start; diff --git a/tests/input.at b/tests/input.at index 1548f14c..f05a9895 100644 --- a/tests/input.at +++ b/tests/input.at @@ -64,14 +64,13 @@ AT_CHECK([[$PERL -pi -e 's/\\(\d{3})/chr(oct($1))/ge' input.y || exit 77]]) AT_BISON_CHECK([input.y], [1], [], [[input.y:1.1-2: error: invalid characters: '\0\001\002\377?' input.y:3.1: error: invalid character: '?' -input.y:4.14: error: invalid character: '}' +input.y:4.14: error: syntax error, unexpected } input.y:5.1: error: invalid character: '%' input.y:5.2: error: invalid character: '&' input.y:6.1-17: error: invalid directive: '%a-does-not-exist' input.y:7.1: error: invalid character: '%' input.y:7.2: error: invalid character: '-' input.y:8.1-9.0: error: missing '%}' at end of file -input.y:8.1-9.0: error: syntax error, unexpected %{...%} ]]) AT_CLEANUP diff --git a/tests/regression.at b/tests/regression.at index b9ca94c0..f2edccc9 100644 --- a/tests/regression.at +++ b/tests/regression.at @@ -405,14 +405,13 @@ default: 'a' } AT_BISON_CHECK([input.y], [1], [], [[input.y:2.1: error: invalid character: '?' -input.y:3.14: error: invalid character: '}' +input.y:3.14: error: syntax error, unexpected } input.y:4.1: error: invalid character: '%' input.y:4.2: error: invalid character: '&' input.y:5.1-17: error: invalid directive: '%a-does-not-exist' input.y:6.1: error: invalid character: '%' input.y:6.2: error: invalid character: '-' input.y:7.1-8.0: error: missing '%}' at end of file -input.y:7.1-8.0: error: syntax error, unexpected %{...%} ]]) AT_CLEANUP