* doc/bison.texinfo: Prefer "continue" to empty loop bodies.
Add some @group/@end group to avoid poor page breaks.
/* Skip white space. */
while ((c = getchar ()) == ' ' || c == '\t')
/* Skip white space. */
while ((c = getchar ()) == ' ' || c == '\t')
@end group
@group
/* Process numbers. */
@end group
@group
/* Process numbers. */
/* Return a single char, and update location. */
if (c == '\n')
@{
/* Return a single char, and update location. */
if (c == '\n')
@{
++yylloc.last_column;
return c;
@}
++yylloc.last_column;
return c;
@}
@end example
Basically, the lexical analyzer performs the same processing as before:
@end example
Basically, the lexical analyzer performs the same processing as before:
Here is a sample session with the multi-function calculator:
@example
Here is a sample session with the multi-function calculator:
@example
$ @kbd{mfcalc}
@kbd{pi = 3.141592653589}
@result{} 3.1415926536
$ @kbd{mfcalc}
@kbd{pi = 3.141592653589}
@result{} 3.1415926536
@kbd{sin(pi)}
@result{} 0.0000000000
@kbd{sin(pi)}
@result{} 0.0000000000
@kbd{alpha = beta1 = 2.3}
@result{} 2.3000000000
@kbd{alpha}
@kbd{alpha = beta1 = 2.3}
@result{} 2.3000000000
@kbd{alpha}
#include <stdlib.h> /* malloc. */
#include <string.h> /* strlen. */
#include <stdlib.h> /* malloc. */
#include <string.h> /* strlen. */
symrec *
putsym (char const *sym_name, int sym_type)
@{
symrec *
putsym (char const *sym_name, int sym_type)
@{
sym_table = ptr;
return ptr;
@}
sym_table = ptr;
return ptr;
@}
symrec *
getsym (char const *sym_name)
@{
symrec *
getsym (char const *sym_name)
@{
@end smallexample
@node Mfcalc Lexer
@end smallexample
@node Mfcalc Lexer
int c;
/* Ignore white space, get first nonwhite character. */
int c;
/* Ignore white space, get first nonwhite character. */
- while ((c = getchar ()) == ' ' || c == '\t');
+ while ((c = getchar ()) == ' ' || c == '\t')
+ continue;
Thus, they belong in one or more @code{%code requires}:
@smallexample
Thus, they belong in one or more @code{%code requires}:
@smallexample
%code top @{
#define _GNU_SOURCE
#include <stdio.h>
@}
%code top @{
#define _GNU_SOURCE
#include <stdio.h>
@}
%code requires @{
#include "ptypes.h"
@}
%code requires @{
#include "ptypes.h"
@}
%union @{
long int n;
tree t; /* @r{@code{tree} is defined in @file{ptypes.h}.} */
@}
%union @{
long int n;
tree t; /* @r{@code{tree} is defined in @file{ptypes.h}.} */
@}
%code requires @{
#define YYLTYPE YYLTYPE
typedef struct YYLTYPE
%code requires @{
#define YYLTYPE YYLTYPE
typedef struct YYLTYPE
char *filename;
@} YYLTYPE;
@}
char *filename;
@} YYLTYPE;
@}
%code @{
static void print_token_value (FILE *, int, YYSTYPE);
#define YYPRINT(F, N, L) print_token_value (F, N, L)
static void trace_token (enum yytokentype token, YYLTYPE loc);
@}
%code @{
static void print_token_value (FILE *, int, YYSTYPE);
#define YYPRINT(F, N, L) print_token_value (F, N, L)
static void trace_token (enum yytokentype token, YYLTYPE loc);
@}
@dots{}
@end smallexample
@dots{}
@end smallexample
@code{%code} to a @code{%code provides}:
@smallexample
@code{%code} to a @code{%code provides}:
@smallexample
%code top @{
#define _GNU_SOURCE
#include <stdio.h>
@}
%code top @{
#define _GNU_SOURCE
#include <stdio.h>
@}
%code requires @{
#include "ptypes.h"
@}
%code requires @{
#include "ptypes.h"
@}
%union @{
long int n;
tree t; /* @r{@code{tree} is defined in @file{ptypes.h}.} */
@}
%union @{
long int n;
tree t; /* @r{@code{tree} is defined in @file{ptypes.h}.} */
@}
%code requires @{
#define YYLTYPE YYLTYPE
typedef struct YYLTYPE
%code requires @{
#define YYLTYPE YYLTYPE
typedef struct YYLTYPE
char *filename;
@} YYLTYPE;
@}
char *filename;
@} YYLTYPE;
@}
%code provides @{
void trace_token (enum yytokentype token, YYLTYPE loc);
@}
%code provides @{
void trace_token (enum yytokentype token, YYLTYPE loc);
@}
%code @{
static void print_token_value (FILE *, int, YYSTYPE);
#define YYPRINT(F, N, L) print_token_value (F, N, L)
@}
%code @{
static void print_token_value (FILE *, int, YYSTYPE);
#define YYPRINT(F, N, L) print_token_value (F, N, L)
@}
@dots{}
@end smallexample
@dots{}
@end smallexample
%code requires @{ #include "type1.h" @}
%union @{ type1 field1; @}
%destructor @{ type1_free ($$); @} <field1>
%printer @{ type1_print ($$); @} <field1>
%code requires @{ #include "type1.h" @}
%union @{ type1 field1; @}
%destructor @{ type1_free ($$); @} <field1>
%printer @{ type1_print ($$); @} <field1>
%code requires @{ #include "type2.h" @}
%union @{ type2 field2; @}
%destructor @{ type2_free ($$); @} <field2>
%printer @{ type2_print ($$); @} <field2>
%code requires @{ #include "type2.h" @}
%union @{ type2 field2; @}
%destructor @{ type2_free ($$); @} <field2>
%printer @{ type2_print ($$); @} <field2>
@end smallexample
@noindent
@end smallexample
@noindent
of zero or more @code{word} groupings.
@example
of zero or more @code{word} groupings.
@example
sequence: /* empty */
@{ printf ("empty sequence\n"); @}
| maybeword
| sequence word
@{ printf ("added word %s\n", $2); @}
;
sequence: /* empty */
@{ printf ("empty sequence\n"); @}
| maybeword
| sequence word
@{ printf ("added word %s\n", $2); @}
;
maybeword: /* empty */
@{ printf ("empty maybeword\n"); @}
| word
@{ printf ("single word %s\n", $1); @}
;
maybeword: /* empty */
@{ printf ("empty maybeword\n"); @}
| word
@{ printf ("single word %s\n", $1); @}
;
from being empty:
@example
from being empty:
@example
sequence: /* empty */
| sequence words
| sequence redirects
;
sequence: /* empty */
| sequence words
| sequence redirects
;
words: word
| words word
;
words: word
| words word
;
redirects:redirect
| redirects redirect
;
redirects:redirect
| redirects redirect
;
@end example
@node Mysterious Conflicts
@end example
@node Mysterious Conflicts
@example
typedef int foo, bar;
int baz (void)
@example
typedef int foo, bar;
int baz (void)
@{
static bar (bar); /* @r{redeclare @code{bar} as static variable} */
extern foo foo (foo); /* @r{redeclare @code{foo} as function} */
return foo (bar);
@}
@{
static bar (bar); /* @r{redeclare @code{bar} as static variable} */
extern foo foo (foo); /* @r{redeclare @code{foo} as function} */
return foo (bar);
@}
@end example
Unfortunately, the name being declared is separated from the declaration
@end example
Unfortunately, the name being declared is separated from the declaration
duplication, with actions omitted for brevity:
@example
duplication, with actions omitted for brevity:
@example
initdcl:
declarator maybeasm '='
init
| declarator maybeasm
;
initdcl:
declarator maybeasm '='
init
| declarator maybeasm
;
notype_initdcl:
notype_declarator maybeasm '='
init
| notype_declarator maybeasm
;
notype_initdcl:
notype_declarator maybeasm '='
init
| notype_declarator maybeasm
;
and reports the uses of the symbols:
@example
and reports the uses of the symbols:
@example
Terminals, with rules where they appear
$end (0) 0
Terminals, with rules where they appear
$end (0) 0
'/' (47) 4
error (256)
NUM (258) 5
'/' (47) 4
error (256)
NUM (258) 5
Nonterminals, with rules where they appear
$accept (8)
on left: 0
exp (9)
on left: 1 2 3 4 5, on right: 0 1 2 3 4
Nonterminals, with rules where they appear
$accept (8)
on left: 0
exp (9)
on left: 1 2 3 4 5, on right: 0 1 2 3 4
The remaining states are similar:
@example
The remaining states are similar:
@example
state 9
exp -> exp . '+' exp (rule 1)
state 9
exp -> exp . '+' exp (rule 1)
'/' [reduce using rule 2 (exp)]
$default reduce using rule 2 (exp)
'/' [reduce using rule 2 (exp)]
$default reduce using rule 2 (exp)
state 10
exp -> exp . '+' exp (rule 1)
state 10
exp -> exp . '+' exp (rule 1)
'/' [reduce using rule 3 (exp)]
$default reduce using rule 3 (exp)
'/' [reduce using rule 3 (exp)]
$default reduce using rule 3 (exp)
state 11
exp -> exp . '+' exp (rule 1)
state 11
exp -> exp . '+' exp (rule 1)
'*' [reduce using rule 4 (exp)]
'/' [reduce using rule 4 (exp)]
$default reduce using rule 4 (exp)
'*' [reduce using rule 4 (exp)]
'/' [reduce using rule 4 (exp)]
$default reduce using rule 4 (exp)
@comment file: calc++-scanner.ll
@example
@comment file: calc++-scanner.ll
@example
%@{
// Code run each time a pattern is matched.
# define YY_USER_ACTION loc.columns (yyleng);
%@}
%@{
// Code run each time a pattern is matched.
# define YY_USER_ACTION loc.columns (yyleng);
%@}
%@{
// Code run each time yylex is called.
loc.step ();
%@}
%@{
// Code run each time yylex is called.
loc.step ();
%@}
@{blank@}+ loc.step ();
[\n]+ loc.lines (yyleng); loc.step ();
@end example
@{blank@}+ loc.step ();
[\n]+ loc.lines (yyleng); loc.step ();
@end example
")" return yy::calcxx_parser::make_RPAREN(loc);
":=" return yy::calcxx_parser::make_ASSIGN(loc);
")" return yy::calcxx_parser::make_RPAREN(loc);
":=" return yy::calcxx_parser::make_ASSIGN(loc);
@{int@} @{
errno = 0;
long n = strtol (yytext, NULL, 10);
@{int@} @{
errno = 0;
long n = strtol (yytext, NULL, 10);
driver.error (loc, "integer is out of range");
return yy::calcxx_parser::make_NUMBER(n, loc);
@}
driver.error (loc, "integer is out of range");
return yy::calcxx_parser::make_NUMBER(n, loc);
@}
@{id@} return yy::calcxx_parser::make_IDENTIFIER(yytext, loc);
. driver.error (loc, "invalid character");
<<EOF>> return yy::calcxx_parser::make_END(loc);
@{id@} return yy::calcxx_parser::make_IDENTIFIER(yytext, loc);
. driver.error (loc, "invalid character");
<<EOF>> return yy::calcxx_parser::make_END(loc);
@comment file: calc++-scanner.ll
@example
@comment file: calc++-scanner.ll
@example
void
calcxx_driver::scan_begin ()
@{
void
calcxx_driver::scan_begin ()
@{
exit (EXIT_FAILURE);
@}
@}
exit (EXIT_FAILURE);
@}
@}
void
calcxx_driver::scan_end ()
@{
fclose (yyin);
@}
void
calcxx_driver::scan_end ()
@{
fclose (yyin);
@}
@end example
@node Calc++ Top Level
@end example
@node Calc++ Top Level
#include <iostream>
#include "calc++-driver.hh"
#include <iostream>
#include "calc++-driver.hh"
int
main (int argc, char *argv[])
@{
int
main (int argc, char *argv[])
@{
@end example
@node Java Parsers
@end example
@node Java Parsers
demonstration, consider the following source file,
@file{first-line.l}:
demonstration, consider the following source file,
@file{first-line.l}:
#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
%%
.*\n ECHO; return 1;
%%
%%
.*\n ECHO; return 1;
%%
int
yyparse (char const *file)
int
yyparse (char const *file)
yyin = fopen (file, "r");
if (!yyin)
yyin = fopen (file, "r");
if (!yyin)
- {
- perror ("fopen");
- exit (EXIT_FAILURE);
- }
+ @{
+ perror ("fopen");
+ exit (EXIT_FAILURE);
+ @}
+@end group
+@group
/* One token only. */
yylex ();
if (fclose (yyin) != 0)
/* One token only. */
yylex ();
if (fclose (yyin) != 0)
- {
- perror ("fclose");
- exit (EXIT_FAILURE);
- }
+ @{
+ perror ("fclose");
+ exit (EXIT_FAILURE);
+ @}
yyparse ("input");
yyparse ("input");
return 0;
yyparse ("input");
yyparse ("input");
return 0;
+@}
+@end group
+@end example
@noindent
If the file @file{input} contains
@noindent
If the file @file{input} contains
of the scanner. Consider the following Lex code:
@verbatim
of the scanner. Consider the following Lex code:
@verbatim
%{
#include <stdio.h>
char *yylval = NULL;
%}
%{
#include <stdio.h>
char *yylval = NULL;
%}
%%
.* yylval = yytext; return 1;
\n /* IGNORE */
%%
%%
.* yylval = yytext; return 1;
\n /* IGNORE */
%%
printf ("\"%s\", \"%s\"\n", fst, snd);
return 0;
}
printf ("\"%s\", \"%s\"\n", fst, snd);
return 0;
}
@end verbatim
If you compile and run this code, you get:
@end verbatim
If you compile and run this code, you get: