447 |
|
|
448 |
Here is a simple C function subdivided into tokens: |
Here is a simple C function subdivided into tokens: |
449 |
|
|
450 |
|
@ifinfo |
451 |
|
@example |
452 |
|
int /* @r{keyword `int'} */ |
453 |
|
square (int x) /* @r{identifier, open-paren, identifier,} |
454 |
|
@r{identifier, close-paren} */ |
455 |
|
@{ /* @r{open-brace} */ |
456 |
|
return x * x; /* @r{keyword `return', identifier, asterisk, |
457 |
|
identifier, semicolon} */ |
458 |
|
@} /* @r{close-brace} */ |
459 |
|
@end example |
460 |
|
@end ifinfo |
461 |
|
@ifnotinfo |
462 |
@example |
@example |
463 |
int /* @r{keyword `int'} */ |
int /* @r{keyword `int'} */ |
464 |
square (x) /* @r{identifier, open-paren,} */ |
square (int x) /* @r{identifier, open-paren, identifier, identifier, close-paren} */ |
|
/* @r{identifier, close-paren} */ |
|
|
int x; /* @r{keyword `int', identifier, semicolon} */ |
|
465 |
@{ /* @r{open-brace} */ |
@{ /* @r{open-brace} */ |
466 |
return x * x; /* @r{keyword `return', identifier,} */ |
return x * x; /* @r{keyword `return', identifier, asterisk, identifier, semicolon} */ |
|
/* @r{asterisk, identifier, semicolon} */ |
|
467 |
@} /* @r{close-brace} */ |
@} /* @r{close-brace} */ |
468 |
@end example |
@end example |
469 |
|
@end ifnotinfo |
470 |
|
|
471 |
The syntactic groupings of C include the expression, the statement, the |
The syntactic groupings of C include the expression, the statement, the |
472 |
declaration, and the function definition. These are represented in the |
declaration, and the function definition. These are represented in the |
1214 |
@example |
@example |
1215 |
@group |
@group |
1216 |
# @r{List files in current directory.} |
# @r{List files in current directory.} |
1217 |
% ls |
$ @kbd{ls} |
1218 |
rpcalc.tab.c rpcalc.y |
rpcalc.tab.c rpcalc.y |
1219 |
@end group |
@end group |
1220 |
|
|
1221 |
@group |
@group |
1222 |
# @r{Compile the Bison parser.} |
# @r{Compile the Bison parser.} |
1223 |
# @r{@samp{-lm} tells compiler to search math library for @code{pow}.} |
# @r{@samp{-lm} tells compiler to search math library for @code{pow}.} |
1224 |
% cc rpcalc.tab.c -lm -o rpcalc |
$ @kbd{cc rpcalc.tab.c -lm -o rpcalc} |
1225 |
@end group |
@end group |
1226 |
|
|
1227 |
@group |
@group |
1228 |
# @r{List files again.} |
# @r{List files again.} |
1229 |
% ls |
$ @kbd{ls} |
1230 |
rpcalc rpcalc.tab.c rpcalc.y |
rpcalc rpcalc.tab.c rpcalc.y |
1231 |
@end group |
@end group |
1232 |
@end example |
@end example |
1235 |
example session using @code{rpcalc}. |
example session using @code{rpcalc}. |
1236 |
|
|
1237 |
@example |
@example |
1238 |
% rpcalc |
$ @kbd{rpcalc} |
1239 |
4 9 + |
@kbd{4 9 +} |
1240 |
13 |
13 |
1241 |
3 7 + 3 4 5 *+- |
@kbd{3 7 + 3 4 5 *+-} |
1242 |
-13 |
-13 |
1243 |
3 7 + 3 4 5 * + - n @r{Note the unary minus, @samp{n}} |
@kbd{3 7 + 3 4 5 * + - n} @r{Note the unary minus, @samp{n}} |
1244 |
13 |
13 |
1245 |
5 6 / 4 n + |
@kbd{5 6 / 4 n +} |
1246 |
-3.166666667 |
-3.166666667 |
1247 |
3 4 ^ @r{Exponentiation} |
@kbd{3 4 ^} @r{Exponentiation} |
1248 |
81 |
81 |
1249 |
^D @r{End-of-file indicator} |
@kbd{^D} @r{End-of-file indicator} |
1250 |
% |
$ |
1251 |
@end example |
@end example |
1252 |
|
|
1253 |
@node Infix Calc |
@node Infix Calc |
1327 |
|
|
1328 |
@need 500 |
@need 500 |
1329 |
@example |
@example |
1330 |
% calc |
$ @kbd{calc} |
1331 |
4 + 4.5 - (34/(8*3+-3)) |
@kbd{4 + 4.5 - (34/(8*3+-3))} |
1332 |
6.880952381 |
6.880952381 |
1333 |
-56 + 2 |
@kbd{-56 + 2} |
1334 |
-54 |
-54 |
1335 |
3 ^ 2 |
@kbd{3 ^ 2} |
1336 |
9 |
9 |
1337 |
@end example |
@end example |
1338 |
|
|
1384 |
@cindex @code{ltcalc} |
@cindex @code{ltcalc} |
1385 |
@cindex calculator, location tracking |
@cindex calculator, location tracking |
1386 |
|
|
1387 |
This example extends the infix notation calculator with location tracking. |
This example extends the infix notation calculator with location |
1388 |
This feature will be used to improve error reporting, and provide better |
tracking. This feature will be used to improve the error messages. For |
1389 |
error messages. |
the sake of clarity, this example is a simple integer calculator, since |
1390 |
|
most of the work needed to use locations will be done in the lexical |
1391 |
For the sake of clarity, we will switch for this example to an integer |
analyser. |
|
calculator, since most of the work needed to use locations will be done |
|
|
in the lexical analyser. |
|
1392 |
|
|
1393 |
@menu |
@menu |
1394 |
* Decls: Ltcalc Decls. Bison and C declarations for ltcalc. |
* Decls: Ltcalc Decls. Bison and C declarations for ltcalc. |
1399 |
@node Ltcalc Decls |
@node Ltcalc Decls |
1400 |
@subsection Declarations for @code{ltcalc} |
@subsection Declarations for @code{ltcalc} |
1401 |
|
|
1402 |
The C and Bison declarations for the location tracking calculator are the same |
The C and Bison declarations for the location tracking calculator are |
1403 |
as the declarations for the infix notation calculator. |
the same as the declarations for the infix notation calculator. |
1404 |
|
|
1405 |
@example |
@example |
1406 |
/* Location tracking calculator. */ |
/* Location tracking calculator. */ |
1421 |
%% /* Grammar follows */ |
%% /* Grammar follows */ |
1422 |
@end example |
@end example |
1423 |
|
|
1424 |
In the code above, there are no declarations specific to locations. Defining |
@noindent |
1425 |
a data type for storing locations is not needed: we will use the type provided |
Note there are no declarations specific to locations. Defining a data |
1426 |
by default (@pxref{Location Type, ,Data Types of Locations}), which is a four |
type for storing locations is not needed: we will use the type provided |
1427 |
member structure with the following integer fields: @code{first_line}, |
by default (@pxref{Location Type, ,Data Types of Locations}), which is a |
1428 |
@code{first_column}, @code{last_line} and @code{last_column}. |
four member structure with the following integer fields: |
1429 |
|
@code{first_line}, @code{first_column}, @code{last_line} and |
1430 |
|
@code{last_column}. |
1431 |
|
|
1432 |
@node Ltcalc Rules |
@node Ltcalc Rules |
1433 |
@subsection Grammar Rules for @code{ltcalc} |
@subsection Grammar Rules for @code{ltcalc} |
1434 |
|
|
1435 |
Whether you choose to handle locations or not has no effect on the syntax of |
Whether handling locations or not has no effect on the syntax of your |
1436 |
your language. Therefore, grammar rules for this example will be very close to |
language. Therefore, grammar rules for this example will be very close |
1437 |
those of the previous example: we will only modify them to benefit from the new |
to those of the previous example: we will only modify them to benefit |
1438 |
informations we will have. |
from the new information. |
1439 |
|
|
1440 |
Here, we will use locations to report divisions by zero, and locate the wrong |
Here, we will use locations to report divisions by zero, and locate the |
1441 |
expressions or subexpressions. |
wrong expressions or subexpressions. |
1442 |
|
|
1443 |
@example |
@example |
1444 |
@group |
@group |
1459 |
| exp '-' exp @{ $$ = $1 - $3; @} |
| exp '-' exp @{ $$ = $1 - $3; @} |
1460 |
| exp '*' exp @{ $$ = $1 * $3; @} |
| exp '*' exp @{ $$ = $1 * $3; @} |
1461 |
@end group |
@end group |
|
| exp '/' exp |
|
1462 |
@group |
@group |
1463 |
|
| exp '/' exp |
1464 |
@{ |
@{ |
1465 |
if ($3) |
if ($3) |
1466 |
$$ = $1 / $3; |
$$ = $1 / $3; |
1467 |
else |
else |
1468 |
@{ |
@{ |
1469 |
$$ = 1; |
$$ = 1; |
1470 |
printf("Division by zero, l%d,c%d-l%d,c%d", |
fprintf (stderr, "%d.%d-%d.%d: division by zero", |
1471 |
@@3.first_line, @@3.first_column, |
@@3.first_line, @@3.first_column, |
1472 |
@@3.last_line, @@3.last_column); |
@@3.last_line, @@3.last_column); |
1473 |
@} |
@} |
1474 |
@} |
@} |
1475 |
@end group |
@end group |
1484 |
using the pseudo-variables @code{@@@var{n}} for rule components, and the |
using the pseudo-variables @code{@@@var{n}} for rule components, and the |
1485 |
pseudo-variable @code{@@$} for groupings. |
pseudo-variable @code{@@$} for groupings. |
1486 |
|
|
1487 |
In this example, we never assign a value to @code{@@$}, because the |
We don't need to assign a value to @code{@@$}: the output parser does it |
1488 |
output parser can do this automatically. By default, before executing |
automatically. By default, before executing the C code of each action, |
1489 |
the C code of each action, @code{@@$} is set to range from the beginning |
@code{@@$} is set to range from the beginning of @code{@@1} to the end |
1490 |
of @code{@@1} to the end of @code{@@@var{n}}, for a rule with @var{n} |
of @code{@@@var{n}}, for a rule with @var{n} components. This behavior |
1491 |
components. |
can be redefined (@pxref{Location Default Action, , Default Action for |
1492 |
|
Locations}), and for very specific rules, @code{@@$} can be computed by |
1493 |
Of course, this behavior can be redefined (@pxref{Location Default |
hand. |
|
Action, , Default Action for Locations}), and for very specific rules, |
|
|
@code{@@$} can be computed by hand. |
|
1494 |
|
|
1495 |
@node Ltcalc Lexer |
@node Ltcalc Lexer |
1496 |
@subsection The @code{ltcalc} Lexical Analyzer. |
@subsection The @code{ltcalc} Lexical Analyzer. |
1497 |
|
|
1498 |
Until now, we relied on Bison's defaults to enable location tracking. The next |
Until now, we relied on Bison's defaults to enable location |
1499 |
step is to rewrite the lexical analyser, and make it able to feed the parser |
tracking. The next step is to rewrite the lexical analyser, and make it |
1500 |
with locations of tokens, as he already does for semantic values. |
able to feed the parser with the token locations, as it already does for |
1501 |
|
semantic values. |
1502 |
|
|
1503 |
To do so, we must take into account every single character of the input text, |
To this end, we must take into account every single character of the |
1504 |
to avoid the computed locations of being fuzzy or wrong: |
input text, to avoid the computed locations of being fuzzy or wrong: |
1505 |
|
|
1506 |
@example |
@example |
1507 |
@group |
@group |
1551 |
@} |
@} |
1552 |
@end example |
@end example |
1553 |
|
|
1554 |
Basically, the lexical analyzer does the same processing as before: it skips |
Basically, the lexical analyzer performs the same processing as before: |
1555 |
blanks and tabs, and reads numbers or single-character tokens. In addition |
it skips blanks and tabs, and reads numbers or single-character tokens. |
1556 |
to this, it updates the @code{yylloc} global variable (of type @code{YYLTYPE}), |
In addition, it updates @code{yylloc}, the global variable (of type |
1557 |
where the location of tokens is stored. |
@code{YYLTYPE}) containing the token's location. |
1558 |
|
|
1559 |
Now, each time this function returns a token, the parser has it's number as |
Now, each time this function returns a token, the parser has its number |
1560 |
well as it's semantic value, and it's position in the text. The last needed |
as well as its semantic value, and its location in the text. The last |
1561 |
change is to initialize @code{yylloc}, for example in the controlling |
needed change is to initialize @code{yylloc}, for example in the |
1562 |
function: |
controlling function: |
1563 |
|
|
1564 |
@example |
@example |
1565 |
|
@group |
1566 |
int |
int |
1567 |
main (void) |
main (void) |
1568 |
@{ |
@{ |
1570 |
yylloc.first_column = yylloc.last_column = 0; |
yylloc.first_column = yylloc.last_column = 0; |
1571 |
return yyparse (); |
return yyparse (); |
1572 |
@} |
@} |
1573 |
|
@end group |
1574 |
@end example |
@end example |
1575 |
|
|
1576 |
Remember that computing locations is not a matter of syntax. Every character |
Remember that computing locations is not a matter of syntax. Every |
1577 |
must be associated to a location update, whether it is in valid input, in |
character must be associated to a location update, whether it is in |
1578 |
comments, in literal strings, and so on... |
valid input, in comments, in literal strings, and so on. |
1579 |
|
|
1580 |
@node Multi-function Calc |
@node Multi-function Calc |
1581 |
@section Multi-Function Calculator: @code{mfcalc} |
@section Multi-Function Calculator: @code{mfcalc} |
1605 |
Here is a sample session with the multi-function calculator: |
Here is a sample session with the multi-function calculator: |
1606 |
|
|
1607 |
@example |
@example |
1608 |
% mfcalc |
$ @kbd{mfcalc} |
1609 |
pi = 3.141592653589 |
@kbd{pi = 3.141592653589} |
1610 |
3.1415926536 |
3.1415926536 |
1611 |
sin(pi) |
@kbd{sin(pi)} |
1612 |
0.0000000000 |
0.0000000000 |
1613 |
alpha = beta1 = 2.3 |
@kbd{alpha = beta1 = 2.3} |
1614 |
2.3000000000 |
2.3000000000 |
1615 |
alpha |
@kbd{alpha} |
1616 |
2.3000000000 |
2.3000000000 |
1617 |
ln(alpha) |
@kbd{ln(alpha)} |
1618 |
0.8329091229 |
0.8329091229 |
1619 |
exp(ln(beta1)) |
@kbd{exp(ln(beta1))} |
1620 |
2.3000000000 |
2.3000000000 |
1621 |
% |
$ |
1622 |
@end example |
@end example |
1623 |
|
|
1624 |
Note that multiple assignment and nested function calls are permitted. |
Note that multiple assignment and nested function calls are permitted. |