📄 calc.at
字号:
# Simple calculator. -*- Autotest -*-# Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.# This program is free software; you can redistribute it and/or modify# it under the terms of the GNU General Public License as published by# the Free Software Foundation; either version 2, or (at your option)# any later version.# This program is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the# GNU General Public License for more details.# You should have received a copy of the GNU General Public License# along with this program; if not, write to the Free Software# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA# 02111-1307, USA.## ---------------------------------------------------- #### Compile the grammar described in the documentation. #### ---------------------------------------------------- ### ------------------------- ## Helping Autotest macros. ## ------------------------- ## _AT_DATA_CALC_Y($1, $2, $3, [BISON-DIRECTIVES])# -----------------------------------------------# Produce `calc.y'. Don't call this macro directly, because it contains# some occurrences of `$1' etc. which will be interpreted by m4. So# you should call it with $1, $2, and $3 as arguments, which is what# AT_DATA_CALC_Y does.m4_define([_AT_DATA_CALC_Y],[m4_if([$1$2$3], $[1]$[2]$[3], [], [m4_fatal([$0: Invalid arguments: $@])])dnlAT_DATA_GRAMMAR([calc.y],[[/* Infix notation calculator--calc */]$4[%{#include <stdio.h>#include <stdlib.h>#include <string.h>#if HAVE_UNISTD_H# include <unistd.h>#else# undef alarm# define alarm(seconds) /* empty */#endif#include <ctype.h>/* Exercise pre-prologue dependency to %union. */typedef int semantic_value;static semantic_value global_result = 0;static int global_count = 0;%}/* Exercise %union. */%union{ semantic_value ival;};%{static int power (int base, int exponent);]AT_LALR1_CC_IF([typedef yy::location YYLTYPE;],[/* yyerror receives the location if: - %location & %pure & %glr - %location & %pure & %yacc & %parse-param. */static void yyerror (AT_YYERROR_ARG_LOC_IF([YYLTYPE *yylloc, ]) AT_PARAM_IF([semantic_value *result, int *count, ]) const char *s );])[static int yylex (]AT_LEX_FORMALS[);static int yygetc (]AT_LEX_FORMALS[);static void yyungetc (]AT_LEX_PRE_FORMALS[ int c);%}/* Bison Declarations */%token CALC_EOF 0 "end of input"%token <ival> NUM "number"%type <ival> exp%nonassoc '=' /* comparison */%left '-' '+'%left '*' '/'%left NEG /* negation--unary minus */%right '^' /* exponentiation *//* Grammar follows */%%input: line| input line { ]AT_PARAM_IF([++*count; ++global_count;])[ };line: '\n'| exp '\n' { ]AT_PARAM_IF([*result = global_result = $1;])[ };exp: NUM { $$ = $1; }| exp '=' exp { if ($1 != $3) fprintf (stderr, "calc: error: %d != %d\n", $1, $3); $$ = $1; }| exp '+' exp { $$ = $1 + $3; }| exp '-' exp { $$ = $1 - $3; }| exp '*' exp { $$ = $1 * $3; }| exp '/' exp { $$ = $1 / $3; }| '-' exp %prec NEG { $$ = -$2; }| exp '^' exp { $$ = power ($1, $3); }| '(' exp ')' { $$ = $2; }| '(' error ')' { $$ = 1111; }| '!' { YYERROR; }| '-' error { YYERROR; };%%/* The input. */static FILE *yyin;]AT_LALR1_CC_IF([/* A C++ error reporting function. */voidyy::parser::error (const location& l, const std::string& m){ (void) l; std::cerr << AT_LOCATION_IF([l << ": " << ])m << std::endl;}intyyparse (AT_PARAM_IF([semantic_value *result, int *count])){ yy::parser parser[]AT_PARAM_IF([ (result, count)]); parser.set_debug_level (!!YYDEBUG); return parser.parse ();}],[static voidyyerror (AT_YYERROR_ARG_LOC_IF([YYLTYPE *yylloc, ]) AT_PARAM_IF([semantic_value *result, int *count, ]) const char *s){AT_PARAM_IF([(void) result; (void) count;])AT_YYERROR_SEES_LOC_IF([ fprintf (stderr, "%d.%d", AT_LOC.first_line, AT_LOC.first_column); if (AT_LOC.first_line != AT_LOC.last_line) fprintf (stderr, "-%d.%d", AT_LOC.last_line, AT_LOC.last_column - 1); else if (AT_LOC.first_column != AT_LOC.last_column - 1) fprintf (stderr, "-%d", AT_LOC.last_column - 1); fprintf (stderr, ": ");]) fprintf (stderr, "%s\n", s);}])[]AT_LOCATION_IF([static YYLTYPE last_yylloc;])[static intyygetc (]AT_LEX_FORMALS[){ int res = getc (yyin); ]AT_USE_LEX_ARGS[;]AT_LOCATION_IF([ last_yylloc = AT_LOC; if (res == '\n') {AT_LALR1_CC_IF([ AT_LOC.end.line++; AT_LOC.end.column = 0;],[ AT_LOC.last_line++; AT_LOC.last_column = 0;]) } elseAT_LALR1_CC_IF([ AT_LOC.end.column++;],[ AT_LOC.last_column++;])])[ return res;}static voidyyungetc (]AT_LEX_PRE_FORMALS[ int c){ ]AT_USE_LEX_ARGS[;]AT_LOCATION_IF([ /* Wrong when C == `\n'. */ AT_LOC = last_yylloc;])[ ungetc (c, yyin);}static intread_signed_integer (]AT_LEX_FORMALS[){ int c = yygetc (]AT_LEX_ARGS[); int sign = 1; int n = 0; ]AT_USE_LEX_ARGS[; if (c == '-') { c = yygetc (]AT_LEX_ARGS[); sign = -1; } while (isdigit (c)) { n = 10 * n + (c - '0'); c = yygetc (]AT_LEX_ARGS[); } yyungetc (]AT_LEX_PRE_ARGS[ c); return sign * n;}/*---------------------------------------------------------------.| Lexical analyzer returns an integer on the stack and the token || NUM, or the ASCII character read if not a number. Skips all || blanks and tabs, returns 0 for EOF. |`---------------------------------------------------------------*/static intyylex (]AT_LEX_FORMALS[){ static int init = 1; int c; if (init) { init = 0;]AT_LALR1_CC_IF([],[AT_LOCATION_IF([ AT_LOC.last_column = 0; AT_LOC.last_line = 1;])])[ }]AT_LOCATION_IF([AT_LALR1_CC_IF([ AT_LOC.begin = AT_LOC.end;],[ AT_LOC.first_column = AT_LOC.last_column; AT_LOC.first_line = AT_LOC.last_line;])])[ /* Skip white space. */ while ((c = yygetc (]AT_LEX_ARGS[)) == ' ' || c == '\t') {]AT_LOCATION_IF([AT_LALR1_CC_IF([ AT_LOC.begin = AT_LOC.end;],[ AT_LOC.first_column = AT_LOC.last_column; AT_LOC.first_line = AT_LOC.last_line;])])[ } /* process numbers */ if (c == '.' || isdigit (c)) { yyungetc (]AT_LEX_PRE_ARGS[ c); ]AT_VAL[.ival = read_signed_integer (]AT_LEX_ARGS[); return NUM; } /* Return end-of-file. */ if (c == EOF) return CALC_EOF; /* Return single chars. */ return c;}static intpower (int base, int exponent){ int res = 1; if (exponent < 0) exit (1); for (/* Niente */; exponent; --exponent) res *= base; return res;}intmain (int argc, const char **argv){ semantic_value result = 0; int count = 0; int status; alarm (10); if (argc == 2) yyin = fopen (argv[1], "r"); else yyin = stdin; if (!yyin) { perror (argv[1]); exit (1); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -