Created
November 1, 2015 12:44
-
-
Save YieldNull/09793e361c226fc9ae17 to your computer and use it in GitHub Desktop.
Recognize C Pointer Declaration(识别C语言指针表达式)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* R2LParser.c | |
* | |
* Recognize C declaration use Right-Left Method(from http://ieng9.ucsd.edu/~cs30x/rt_lt.rule.html) | |
* | |
* The "right-left" rule is a completely regular rule for deciphering C | |
* declarations. It can also be useful in creating them. | |
* | |
* First, symbols. Read | |
* * as "pointer to" - always on the left side | |
* [] as "array of" - always on the right side | |
* () as "function returning" - always on the right side | |
* | |
* as you encounter them in the declaration. | |
* | |
* STEP 1 | |
* ------ | |
* Find the identifier. This is your starting point. Then say to yourself, | |
* "identifier is." You've started your declaration. | |
* | |
* STEP 2 | |
* ------ | |
* Look at the symbols on the right of the identifier. If, say, you find "()" | |
* there, then you know that this is the declaration for a function. So you | |
* would then have "identifier is function returning". Or if you found a | |
* "[]" there, you would say "identifier is array of". Continue right until | |
* you run out of symbols *OR* hit a *right* parenthesis ")". (If you hit a | |
* left parenthesis, that's the beginning of a () symbol, even if there | |
* is stuff in between the parentheses. More on that below.) | |
* | |
* STEP 3 | |
* ------ | |
* Look at the symbols to the left of the identifier. If it is not one of our | |
* symbols above (say, something like "int"), just say it. Otherwise, translate | |
* it into English using that table above. Keep going left until you run out of | |
* symbols *OR* hit a *left* parenthesis "(". | |
* | |
* | |
* Created on: Sep 23, 2015 | |
* Author: hejunjie.net | |
*/ | |
#include <stdio.h> | |
#include <string.h> | |
#include <ctype.h> | |
#define MAXLENGTH 100 // the max length of a token | |
#define BUFSIZE 100 // buffer size | |
/* user defined token type */ | |
enum { | |
NAME, PARENTS, BRACKETS | |
}; | |
int tokentype; // token type: NAME, PARENTS, BRACKETS or '\n' etc. | |
char token[MAXLENGTH];// name, pair of parentheses, pair of brackets perhaps including a number, or other single character | |
char name[MAXLENGTH]; // identifier name | |
char datatype[MAXLENGTH]; //char int double etc. | |
char out[1000]; //output string | |
void dcl(void); // consume a declaration | |
void dirdcl(void); // consume a direct declaration | |
int gettoken(void); // read a token from input | |
/* look ahead mechanism*/ | |
char buf[BUFSIZE]; // buffer to store look ahead char | |
int bufp = 0; // next free position in buffer | |
int getch(); // read a char from input or buffer | |
void ungetch(int c); // push char to buffer | |
int main(void) { | |
while (gettoken() != EOF) { // each loop parse one line | |
strcpy(datatype, token); | |
out[0] = '\0'; | |
dcl(); | |
if (tokentype != '\n') | |
printf("syntax error\n"); | |
printf("%s: %s %s\n", name, out, datatype); | |
} | |
return 0; | |
} | |
void dcl(void) { | |
int count = 0; | |
while (gettoken() == '*') { | |
count++; | |
} | |
dirdcl(); | |
while (count-- > 0) { | |
strcat(out, " pointer to"); | |
} | |
} | |
void dirdcl(void) { | |
int type; | |
if (tokentype == '(') { | |
dcl(); | |
if (tokentype != ')') { | |
printf("error: missing )\n"); | |
} | |
} else if (tokentype == NAME) { | |
strcpy(name, token); | |
} else { | |
printf("error: expected name or (dcl)\n"); | |
} | |
while ((type = gettoken()) == PARENTS || type == BRACKETS) { | |
if (type == PARENTS) { | |
strcat(out, " function returning"); | |
} else { | |
strcat(out, " array "); | |
strcat(out, token); | |
strcat(out, " of"); | |
} | |
} | |
} | |
/*read token from input to 'token' array and return token type*/ | |
int gettoken(void) { | |
int c; | |
char *p = token; | |
// consume white char | |
while ((c = getch()) == ' ' || c == '\t') | |
; | |
if (c == '(') { // consume parentheses | |
if ((c = getch()) == ')') { | |
strcpy(token, "()"); | |
return tokentype = PARENTS; | |
} else { | |
ungetch(c); | |
return tokentype = '('; | |
} | |
} else if (c == '[') { // consume brackets | |
for (*p++ = c; (*p++ = getch()) != ']';) | |
; | |
*p = '\0'; | |
return tokentype = BRACKETS; | |
} else if (isalpha(c)) { // consume identifier | |
for (*p++ = c; isalnum(c = getch());) { | |
*p++ = c; | |
} | |
*p = '\0'; | |
ungetch(c); | |
return tokentype = NAME; | |
} else { | |
return tokentype = c; | |
} | |
} | |
int getch(void) { | |
// read char from input or buffer if there exists data | |
return (bufp > 0) ? buf[--bufp] : getchar(); | |
} | |
void ungetch(int c) { | |
// push 'dirty' char back to buffer | |
if (bufp >= BUFSIZE) | |
printf("ungetch: too many characters!"); | |
else | |
buf[bufp++] = c; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment