Instantly share code, notes, and snippets.

/sample2.c
Created Apr 25, 2014

Embed
What would you like to do?
sample 2
#include <assert.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
static void bout(char *msg) __attribute__((noreturn));
static int calc_expr(void);
static int calc_term(void);
static int calc_factor(void);
static void lex_init(void);
static void lex_next(void);
static int lex_token;
static int lex_nextchar;
int
main(void)
{
for (;;) {
lex_init();
if (lex_nextchar == EOF) {
break;
} else if (lex_nextchar != '\n') {
int tmp = calc_expr();
printf("result: %d\n", tmp);
}
if (lex_nextchar != '\n') {
bout("unexpected input");
}
}
return 0;
}
static void
bout(char *msg) /* bailout */
{
fprintf(stderr, "%s\n", msg);
exit(2);
}
/*
* calc
*/
static int
calc_expr(void)
{
/* EXPR = TERM (('+'|'-') TERM)* */
int val = calc_term();
while ((lex_nextchar == '+') || (lex_nextchar == '-')) {
int op, tmp;
lex_next();
op = -lex_token;
tmp = calc_term();
switch (op) {
case '+':
val += tmp;
break;
case '-':
val -= tmp;
break;
default:
assert(0);
}
}
return val;
}
static int
calc_term(void)
{
/* TERM = FACTOR (('*'|'/') FACTOR)* */
int val = calc_factor();
while ((lex_nextchar == '*') || (lex_nextchar == '/')) {
int op, tmp;
lex_next();
op = -lex_token;
tmp = calc_factor();
switch (op) {
case '*':
val *= tmp;
break;
case '/':
val /= tmp;
break;
default:
assert(0);
}
}
return val;
}
static int
calc_factor(void)
{
/* FACTOR = NUM | '(' EXPR ')' */
if (isdigit(lex_nextchar)) {
lex_next();
return lex_token;
} else if (lex_nextchar == '(') { /*)*/
int tmp;
lex_next();
assert(-lex_token == '('); /*)*/
tmp = calc_expr();
/*(*/
if (lex_nextchar != ')') {
bout("syntax error");
}
lex_next(); /*(*/
assert(-lex_token == ')');
return tmp;
}
bout("unexpected input");
}
/*
* lex
*/
static void
lex_init(void)
{
do {
lex_nextchar = getchar();
} while ((lex_nextchar != '\n') && isspace(lex_nextchar));
}
static void
lex_next(void)
{
if (isdigit(lex_nextchar)) {
lex_token = 0;
do {
lex_token = 10 * lex_token + digittoint(lex_nextchar);
lex_nextchar = getchar();
} while (isdigit(lex_nextchar));
} else if ((lex_nextchar == '+') || (lex_nextchar == '-')
|| (lex_nextchar == '*') || (lex_nextchar == '/')
|| (lex_nextchar == '(') || (lex_nextchar == ')')) {
lex_token = -lex_nextchar;
lex_nextchar = getchar();
} else {
bout("unexpected input char");
}
if (lex_nextchar == EOF) {
bout("unexpected EOF");
}
while ((lex_nextchar != '\n') && isspace(lex_nextchar)) {
lex_nextchar = getchar();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment