Instantly share code, notes, and snippets.

/sample1.c
Created Apr 25, 2014

Embed
What would you like to do?
sample 1
#include <assert.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
static void bout(char *msg) __attribute__((noreturn));
static int calc_expr(int val, int op);
static int calc_term(int val, int op);
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(0, '+');
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(int val, int op)
{
int tmp;
/* EXPR = TERM (('+'|'-') EXPR)? */
tmp = calc_term(1, '*');
switch (op) {
case '+':
val += tmp;
break;
case '-':
val -= tmp;
break;
default:
assert(0);
}
if ((lex_nextchar == '+') || (lex_nextchar == '-')) {
lex_next();
switch (-lex_token) {
case '+':
return calc_expr(val, '+');
case '-':
return calc_expr(val, '-');
default:
assert(0);
}
}
return val;
}
static int
calc_term(int val, int op)
{
int tmp;
/* TERM = FACTOR (('*'|'/') TERM)? */
tmp = calc_factor();
switch (op) {
case '*':
val *= tmp;
break;
case '/':
val /= tmp;
break;
default:
assert(0);
}
if ((lex_nextchar == '*') || (lex_nextchar == '/')) {
lex_next();
switch (-lex_token) {
case '*':
return calc_term(val, '*');
case '/':
return calc_term(val, '/');
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(0, '+');
/*(*/
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