[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 3/4] doc: modernize the examples
From: |
Akim Demaille |
Subject: |
[PATCH 3/4] doc: modernize the examples |
Date: |
Sun, 10 Feb 2019 16:48:53 +0100 |
* doc/bison.texi: Prefer 'fun' to 'fnct'.
Reduce local variable scopes.
Prefer strdup to malloc + strcpy.
Avoid gratuitous casts.
Use simpler names (e.g., 'name' instead of 'fname').
Avoid uses of 0 for NULL.
Avoid using NULL when possible (e.g., 'p' instead of 'p != NULL').
Prefer union names to casts (e.g. 'yylval.VAR = s' instead of
'*((symrec**) &yylval) = s').
Give arguments a name in fun declarations.
Use our typedefs instead of duplicating them (func_t).
Stop promoting an explicit $$ = $1;, it should be implicit (Bison
might be able to eliminate useless chain rules).
Help a bit Texinfo by making smaller groups.
Rely on the C compiler to call function pointers (prefer
'$1->value.fun ($3)' to (*($1->value.fnctptr))($3)').
---
doc/bison.texi | 181 +++++++++++++++++++++++++------------------------
1 file changed, 91 insertions(+), 90 deletions(-)
diff --git a/doc/bison.texi b/doc/bison.texi
index 217cbf97..8666e2ff 100644
--- a/doc/bison.texi
+++ b/doc/bison.texi
@@ -1543,7 +1543,8 @@ The source code for this calculator is named
@file{rpcalc.y}. The
@subsection Declarations for @code{rpcalc}
Here are the C and Bison declarations for the Reverse Polish Notation
-calculator. As in C, comments are placed between @samp{/address@hidden/}.
+calculator. As in C, comments are placed between @samp{/address@hidden/} or
+after @samp{//}.
@comment file: rpcalc.y
@example
@@ -1618,7 +1619,7 @@ line:
@group
exp:
- NUM @{ $$ = $1; @}
+ NUM
| exp exp '+' @{ $$ = $1 + $2; @}
| exp exp '-' @{ $$ = $1 - $2; @}
| exp exp '*' @{ $$ = $1 * $2; @}
@@ -1720,9 +1721,10 @@ value of the user's input line, that value is no longer
needed.
@subsubsection Explanation of @code{expr}
The @code{exp} grouping has several rules, one for each kind of expression.
-The first rule handles the simplest expressions: those that are just numbers.
-The second handles an addition-expression, which looks like two expressions
-followed by a plus-sign. The third handles subtraction, and so on.
+The first rule handles the simplest expressions: those that are just
+numbers. The second handles an addition-expression, which looks like two
+expressions followed by a plus-sign. The third handles subtraction, and so
+on.
@example
exp:
@@ -1737,9 +1739,9 @@ We have used @samp{|} to join all the rules for
@code{exp}, but we could
equally well have written them separately:
@example
-exp: NUM ;
-exp: exp exp '+' @{ $$ = $1 + $2; @};
-exp: exp exp '-' @{ $$ = $1 - $2; @};
+exp: NUM;
+exp: exp exp '+' @{ $$ = $1 + $2; @};
+exp: exp exp '-' @{ $$ = $1 - $2; @};
@dots{}
@end example
@@ -1748,17 +1750,21 @@ terms of the value of its parts. For example, in the
rule for addition,
@code{$1} refers to the first component @code{exp} and @code{$2} refers to
the second one. The third component, @code{'+'}, has no meaningful
associated semantic value, but if it had one you could refer to it as
address@hidden When @code{yyparse} recognizes a sum expression using this
-rule, the sum of the two subexpressions' values is produced as the value of
-the entire expression. @xref{Actions}.
address@hidden The first rule relies on the implicit default action:
@address@hidden
+$$ = $1; @}}.
+
+
+When @code{yyparse} recognizes a sum expression using this rule, the sum of
+the two subexpressions' values is produced as the value of the entire
+expression. @xref{Actions}.
-You don't have to give an action for every rule. When a rule has no
-action, Bison by default copies the value of @code{$1} into @code{$$}.
-This is what happens in the first rule (the one that uses @code{NUM}).
+You don't have to give an action for every rule. When a rule has no action,
+Bison by default copies the value of @code{$1} into @code{$$}. This is what
+happens in the first rule (the one that uses @code{NUM}).
-The formatting shown here is the recommended convention, but Bison does
-not require it. You can add or change white space as much as you wish.
-For example, this:
+The formatting shown here is the recommended convention, but Bison does not
+require it. You can add or change white space as much as you wish. For
+example, this:
@example
exp: NUM | exp exp '+' @{$$ = $1 + $2; @} | @dots{} ;
@@ -1831,11 +1837,10 @@ Here is the code for the lexical analyzer:
int
yylex (void)
@{
- int c;
-
+ int c = getchar ();
/* Skip white space. */
- while ((c = getchar ()) == ' ' || c == '\t')
- continue;
+ while (c == ' ' || c == '\t')
+ c = getchar ();
@end group
@group
/* Process numbers. */
@@ -1848,10 +1853,11 @@ yylex (void)
@end group
@group
/* Return end-of-input. */
- if (c == EOF)
+ else if (c == EOF)
return 0;
/* Return a single char. */
- return c;
+ else
+ return c;
@}
@end group
@end example
@@ -2032,7 +2038,7 @@ line:
@group
exp:
- NUM @{ $$ = $1; @}
+ NUM
| exp '+' exp @{ $$ = $1 + $3; @}
| exp '-' exp @{ $$ = $1 - $3; @}
| exp '*' exp @{ $$ = $1 * $3; @}
@@ -2212,7 +2218,7 @@ line:
@group
exp:
- NUM @{ $$ = $1; @}
+ NUM
| exp '+' exp @{ $$ = $1 + $3; @}
| exp '-' exp @{ $$ = $1 - $3; @}
| exp '*' exp @{ $$ = $1 * $3; @}
@@ -2417,8 +2423,8 @@ Here are the C and Bison declarations for the
multi-function calculator.
@end group
%define api.value.type union /* Generate YYSTYPE from these types: */
-%token <double> NUM /* Simple double precision number. */
-%token <symrec*> VAR FNCT /* Symbol table pointer: variable and function.
*/
+%token <double> NUM /* Double precision number. */
+%token <symrec*> VAR FUN /* Symbol table pointer: variable/function. */
%type <double> exp
@group
@@ -2441,7 +2447,7 @@ store these values.
Since values can now have various types, it is necessary to associate a type
with each grammar symbol whose semantic value is used. These symbols are
address@hidden, @code{VAR}, @code{FNCT}, and @code{exp}. Their declarations are
address@hidden, @code{VAR}, @code{FUN}, and @code{exp}. Their declarations are
augmented with their data type (placed between angle brackets). For
instance, values of @code{NUM} are stored in @code{double}.
@@ -2457,7 +2463,7 @@ declared explicitly so we can specify its value type.
@xref{Type Decl,
Here are the grammar rules for the multi-function calculator.
Most of them are copied directly from @code{calc}; three rules,
-those which mention @code{VAR} or @code{FNCT}, are new.
+those which mention @code{VAR} or @code{FUN}, are new.
@comment file: mfcalc.y: 3
@example
@@ -2479,10 +2485,10 @@ line:
@group
exp:
- NUM @{ $$ = $1; @}
+ NUM
| VAR @{ $$ = $1->value.var; @}
| VAR '=' exp @{ $$ = $3; $1->value.var = $3; @}
-| FNCT '(' exp ')' @{ $$ = (*($1->value.fnctptr))($3); @}
+| FUN '(' exp ')' @{ $$ = $1->value.fun ($3); @}
| exp '+' exp @{ $$ = $1 + $3; @}
| exp '-' exp @{ $$ = $1 - $3; @}
| exp '*' exp @{ $$ = $1 * $3; @}
@@ -2513,7 +2519,7 @@ provides for either functions or variables to be placed
in the table.
@example
@group
/* Function type. */
-typedef double (*func_t) (double);
+typedef double (func_t) (double);
@end group
@group
@@ -2521,11 +2527,11 @@ typedef double (*func_t) (double);
struct symrec
@{
char *name; /* name of symbol */
- int type; /* type of symbol: either VAR or FNCT */
+ int type; /* type of symbol: either VAR or FUN */
union
@{
- double var; /* value of a VAR */
- func_t fnctptr; /* value of a FNCT */
+ double var; /* value of a VAR */
+ func_t *fun; /* value of a FUN */
@} value;
struct symrec *next; /* link field */
@};
@@ -2537,8 +2543,8 @@ typedef struct symrec symrec;
/* The symbol table: a chain of 'struct symrec'. */
extern symrec *sym_table;
-symrec *putsym (char const *, int);
-symrec *getsym (char const *);
+symrec *putsym (char const *name, int sym_type);
+symrec *getsym (char const *name);
@end group
@end example
@@ -2550,13 +2556,13 @@ the symbol table:
@group
struct init
@{
- char const *fname;
- double (*fnct) (double);
+ char const *name;
+ func_t *fun;
@};
@end group
@group
-struct init const arith_fncts[] =
+struct init const arith_funs[] =
@{
@{ "atan", atan @},
@{ "cos", cos @},
@@ -2575,15 +2581,15 @@ symrec *sym_table;
@group
/* Put arithmetic functions in table. */
-static
-void
+static void
init_table (void)
address@hidden group
address@hidden
@{
- int i;
- for (i = 0; arith_fncts[i].fname != 0; i++)
+ for (int i = 0; arith_funs[i].name; i++)
@{
- symrec *ptr = putsym (arith_fncts[i].fname, FNCT);
- ptr->value.fnctptr = arith_fncts[i].fnct;
+ symrec *ptr = putsym (arith_funs[i].name, FUN);
+ ptr->value.fun = arith_funs[i].fun;
@}
@}
@end group
@@ -2594,7 +2600,7 @@ files, you can add additional functions to the calculator.
Two important functions allow look-up and installation of symbols in the
symbol table. The function @code{putsym} is passed a name and the type
-(@code{VAR} or @code{FNCT}) of the object to be installed. The object is
+(@code{VAR} or @code{FUN}) of the object to be installed. The object is
linked to the front of the list, and a pointer to the object is returned.
The function @code{getsym} is passed the name of the symbol to look up. If
found, a pointer to that symbol is returned; otherwise zero is returned.
@@ -2606,29 +2612,26 @@ found, a pointer to that symbol is returned; otherwise
zero is returned.
@group
symrec *
-putsym (char const *sym_name, int sym_type)
+putsym (char const *name, int sym_type)
@{
- symrec *ptr = (symrec *) malloc (sizeof (symrec));
- ptr->name = (char *) malloc (strlen (sym_name) + 1);
- strcpy (ptr->name,sym_name);
- ptr->type = sym_type;
- ptr->value.var = 0; /* Set value to 0 even if fctn. */
- ptr->next = (struct symrec *)sym_table;
- sym_table = ptr;
- return ptr;
+ symrec *res = (symrec *) malloc (sizeof (symrec));
+ res->name = strdup (name);
+ res->type = sym_type;
+ res->value.var = 0; /* Set value to 0 even if fun. */
+ res->next = sym_table;
+ sym_table = res;
+ return res;
@}
@end group
@group
symrec *
-getsym (char const *sym_name)
+getsym (char const *name)
@{
- symrec *ptr;
- for (ptr = sym_table; ptr != (symrec *) 0;
- ptr = (symrec *)ptr->next)
- if (strcmp (ptr->name, sym_name) == 0)
- return ptr;
- return 0;
+ for (symrec *p = sym_table; p; p = p->next)
+ if (strcmp (p->name, name) == 0)
+ return p;
+ return NULL;
@}
@end group
@end example
@@ -2643,7 +2646,7 @@ functions depending on what the symbol table says about
them.
The string is passed to @code{getsym} for look up in the symbol table. If
the name appears in the table, a pointer to its location and its type
-(@code{VAR} or @code{FNCT}) is returned to @code{yyparse}. If it is not
+(@code{VAR} or @code{FUN}) is returned to @code{yyparse}. If it is not
already in the table, then it is installed as a @code{VAR} using
@code{putsym}. Again, a pointer and its type (which must be @code{VAR}) is
returned to @code{yyparse}.
@@ -2694,13 +2697,11 @@ Bison generated a definition of @code{YYSTYPE} with a
member named
for a 40-character symbol name. */
static size_t length = 40;
static char *symbuf = 0;
- symrec *s;
- int i;
@end group
if (!symbuf)
- symbuf = (char *) malloc (length + 1);
+ symbuf = malloc (length + 1);
- i = 0;
+ int i = 0;
do
@group
@{
@@ -2708,7 +2709,7 @@ Bison generated a definition of @code{YYSTYPE} with a
member named
if (i == length)
@{
length *= 2;
- symbuf = (char *) realloc (symbuf, length + 1);
+ symbuf = realloc (symbuf, length + 1);
@}
/* Add this character to the buffer. */
symbuf[i++] = c;
@@ -2724,10 +2725,10 @@ Bison generated a definition of @code{YYSTYPE} with a
member named
@end group
@group
- s = getsym (symbuf);
- if (s == 0)
+ symrec *s = getsym (symbuf);
+ if (!s)
s = putsym (symbuf, VAR);
- *((symrec**) &yylval) = s;
+ yylval.VAR = s; /* or yylval.FUN = s. */
return s->type;
@}
@@ -2748,22 +2749,22 @@ on user demand (@xref{Tracing, , Tracing Your Parser},
for details):
@example
@group
/* Called by yyparse on error. */
-void
-yyerror (char const *s)
+void yyerror (char const *s)
@{
fprintf (stderr, "%s\n", s);
@}
@end group
@group
-int
-main (int argc, char const* argv[])
+int main (int argc, char const* argv[])
address@hidden group
address@hidden
@{
- int i;
/* Enable parse traces on option -p. */
- for (i = 1; i < argc; ++i)
- if (!strcmp(argv[i], "-p"))
- yydebug = 1;
+ if (argc == 2 && strcmp(argv[1], "-p") == 0)
+ yydebug = 1;
address@hidden group
address@hidden
init_table ();
return yyparse ();
@}
@@ -7011,9 +7012,9 @@ assuming that the characters of the token are stored in
characters like @samp{"} that require escaping.
@example
-for (i = 0; i < YYNTOKENS; i++)
+for (int i = 0; i < YYNTOKENS; i++)
@{
- if (yytname[i] != 0
+ if (yytname[i]
&& yytname[i][0] == '"'
&& ! strncmp (yytname[i] + 1, token_buffer,
strlen (token_buffer))
@@ -10002,7 +10003,7 @@ prologue:
/* Formatting semantic values. */
%printer @{ fprintf (yyo, "%s", $$->name); @} VAR;
-%printer @{ fprintf (yyo, "%s()", $$->name); @} FNCT;
+%printer @{ fprintf (yyo, "%s()", $$->name); @} FUN;
%printer @{ fprintf (yyo, "%g", $$); @} <double>;
@end example
@@ -10015,7 +10016,7 @@ ill-named) @code{%verbose} directive.
The set of @code{%printer} directives demonstrates how to format the
semantic value in the traces. Note that the specification can be done
-either on the symbol type (e.g., @code{VAR} or @code{FNCT}), or on the type
+either on the symbol type (e.g., @code{VAR} or @code{FUN}), or on the type
tag: since @code{<double>} is the type for both @code{NUM} and @code{exp},
this printer will be used for them.
@@ -10040,13 +10041,13 @@ a valueless (@samp{()}) @code{input} nonterminal
(@code{nterm}).
Then the parser calls the scanner.
@example
-Reading a token: Next token is token FNCT (sin())
-Shifting token FNCT (sin())
+Reading a token: Next token is token FUN (sin())
+Shifting token FUN (sin())
Entering state 6
@end example
@noindent
-That token (@code{token}) is a function (@code{FNCT}) whose value is
+That token (@code{token}) is a function (@code{FUN}) whose value is
@samp{sin} as formatted per our @code{%printer} specification: @samp{sin()}.
The parser stores (@code{Shifting}) that token, and others, until it can do
something about it.
@@ -10101,7 +10102,7 @@ Next token is token ')' ()
Shifting token ')' ()
Entering state 31
Reducing stack by rule 9 (line 47):
- $1 = token FNCT (sin())
+ $1 = token FUN (sin())
$2 = token '(' ()
$3 = nterm exp (0.000000)
$4 = token ')' ()
@@ -14226,8 +14227,8 @@ London, Department of Computer Science, TR-00-12
(December 2000).
@c LocalWords: NUM exp subsubsection kbd Ctrl ctype EOF getchar isdigit nonfree
@c LocalWords: ungetc stdin scanf sc calc ulator ls lm cc NEG prec yyerrok rr
@c LocalWords: longjmp fprintf stderr yylloc YYLTYPE cos ln Stallman Destructor
address@hidden LocalWords: symrec val tptr FNCT fnctptr func struct sym enum
IEC syntaxes
address@hidden LocalWords: fnct putsym getsym fname arith fncts atan ptr malloc
sizeof Lex
address@hidden LocalWords: symrec val tptr FUN func struct sym enum IEC syntaxes
address@hidden LocalWords: fun putsym getsym arith funs atan ptr malloc sizeof
Lex
@c LocalWords: strlen strcpy fctn strcmp isalpha symbuf realloc isalnum DOTDOT
@c LocalWords: ptypes itype YYPRINT trigraphs yytname expseq vindex dtype Unary
@c LocalWords: Rhs YYRHSLOC LE nonassoc op deffn typeless yynerrs nonterminal
--
2.20.1