Académique Documents
Professionnel Documents
Culture Documents
h> #include<stdio.h> char arr[18][3] = { {'E','+','F'},{'E','*','F'},{'E','(','F'},{'E',')','F'},{'E','i','F'},{'E','$','F'}, {'F','+','F'},{'F','*','F'},{'F','(','F'},{'F',')','F'},{'F','i','F'},{'F','$','F'}, {'T','+','F'},{'T','*','F'},{'T','(','F'},{'T',')','F'},{'T','i','F'},{'T','$','F'}, }; char prod[6] = "EETTFF"; char res[6][3]= { {'E','+','T'},{'T','\0'}, {'T','*','F'},{'F','\0'}, {'(','E',')'},{'i','\0'}, }; char stack [5][2]; int top = -1; void install(char pro,char re) { int i; for(i=0;i<18;++i) { if(arr[i][0]==pro && arr[i][1]==re) { arr[i][2] = 'T'; break; } } ++top; stack[top][0]=pro; stack[top][1]=re; } void main() { int i=0,j; char pro,re,pri=' '; clrscr();
for(i=0;i<6;++i) { for(j=0;j<3 && res[i][j]!='\0';++j) { if(res[i][j] =='+'||res[i][j]=='*'||res[i][j]=='('||res[i][j]==')'||res[i][j]=='i'||res[i][j]=='$') { install(prod[i],res[i][j]); break; } } } while(top>=0) { pro = stack[top][0]; re = stack[top][1]; --top; for(i=0;i<6;++i) { if(res[i][0]==pro && res[i][0]!=prod[i]) { install(prod[i],re); } } } for(i=0;i<18;++i) { printf("\n\t"); for(j=0;j<3;++j) printf("%c\t",arr[i][j]); } getch(); clrscr(); printf("\n\n"); for(i=0;i<18;++i) { if(pri!=arr[i][0]) { pri=arr[i][0]; printf("\n\t%c -> ",pri); } if(arr[i][2] =='T') printf("%c ",arr[i][1]); } getch();}
OUTPUT
E E E E E E F F F F F F T T T T T T
+ * ( ) i $ + * ( ) i $ + * ( ) i $
T T T F T F F F T F T F F T T F T F
Below follows a C++ implementation of a table-based LL parser for the example language: #include <iostream> #include <map> #include <stack> enum Symbols { // the symbols: // Terminal symbols: TS_L_PARENS, // ( TS_R_PARENS, // ) TS_A, // a TS_PLUS, // + TS_EOS, // $, in this case corresponds to '\0' TS_INVALID, // invalid token // Non-terminal symbols: NTS_S, // S NTS_F }; /* Converts a valid token to the corresponding terminal symbol */ enum Symbols lexer(char c) { switch(c) { case '(': return TS_L_PARENS; break; case ')': return TS_R_PARENS; break; case 'a': return TS_A; break; case '+': return TS_PLUS; break; case '\0': // this will act as the $ terminal symbol return TS_EOS; break;
default: return TS_INVALID; break; } } int main(int argc, char **argv) { using namespace std; if (argc < 2) { cout << "usage:\n\tll '(a+a)'" << endl; return 0; } // LL parser table, maps < non-terminal, terminal> pair to action map< enum Symbols, map<enum Symbols, int> > table; stack<enum Symbols> ss; // symbol stack char *p; // input buffer // initialize the symbols stack ss.push(TS_EOS); // terminal, $ ss.push(NTS_S); // non-terminal, S // initialize the symbol stream cursor p = &argv[1][0]; // setup the parsing table table[NTS_S][TS_L_PARENS] = 2; table[NTS_S][TS_A] = 1; table[NTS_F][TS_A] = 3; while(ss.size() > 0) { if(lexer(*p) == ss.top()) { cout << "Matched symbols: " << lexer(*p) << endl; p++; ss.pop(); } else { cout << "Rule " << table[ss.top()][lexer(*p)] << endl; switch(table[ss.top()][lexer(*p)]) { case 1: // 1. S F ss.pop(); ss.push(NTS_F); // F break;
case 2: // 2. S ( S + F ) ss.pop(); ss.push(TS_R_PARENS); // ) ss.push(NTS_F); // F ss.push(TS_PLUS); // + ss.push(NTS_S); // S ss.push(TS_L_PARENS); // ( break; case 3: // 3. F a ss.pop(); ss.push(TS_A); break;
// a
default: cout << "parsing table defaulted" << endl; return 0; break; } } } cout << "finished parsing" << endl; return 0; }
1) A Program to Design Lexical Analyzer. #include<string.h> #include<ctype.h> #include<stdio.h>void keyword(char str[10]){if(strcmp("for",str)==0||strcmp("while",str)==0||strcmp("do",str)==0|| strcmp("int",str)==0||strcmp("float",str)==0||strcmp("char",str)==0|| strcmp("double",str)==0||strcmp("static",str)==0||strcmp("switch",str)==0| |strcmp("case",str)==0) printf("\n%s is a keyword",str); else printf("\n%s is an identifier",str); } main() {FILE *f1,*f2,*f3;char c,str[10],st1[10]; int num[100],lineno=0,tokenvalue=0,i=0,j=0,k=0; printf("\nEnter the c program); ;/*gets(st1);*/ f1=fopen("input","w") ;while((c=getchar())!=EOF) putc(c,f1); fclose(f1); f1=fopen("input","r"); f2=fopen("identifier","w"); f3=fopen("specialchar","w"); while((c=getc(f1))!=EOF){if(isdigit(c)) { tokenvalue=c-'0'; c=getc(f1);while(isdigit(c)) { tokenvalue*=10+c-'0';c=getc(f1); }
num[i++]=tokenvalue;ungetc(c,f1); } else if(isalpha(c)) { putc(c,f2);c=getc(f1); while(isdigit(c)||isalpha(c)||c=='_'||c=='$') { putc(c,f2); c=getc(f1); } putc(' ',f2);ungetc(c,f1); } else if(c==' '||c=='\t') printf(" "); else if(c=='\n')lineno++; else putc(c,f3); } fclose(f2) ;fclose(f3); fclose(f1); printf("\nThe no's in the program are); for(j=0;j<i;j++) printf("%d",num[j]); printf("\n"); f2=fopen("identifier","r"); k=0; printf("The keywords and identifiersare:"); while((c=getc(f2))!=EOF) {
if(c!=' ') str[k++]=c; else { str[k]='\0'; keyword(str);k=0; } } fclose(f2); f3=fopen("specialchar","r"); printf("\nSpecial characters are); while((c=getc(f3))!=EOF) printf("%c",c); printf("\n");fclose(f3); printf("Total no. of lines are:%d",lineno); }
Output: Enter the C program a+b*c Ctrl-D The nos in the program are: The keywords and identifiers are: a is an identifier and terminal b is an identifier and terminal c is an identifier and terminal Special characters are: +* Total no. of lines are: 1
The following example shows the contents of the calc.yacc file. This file has entries in all three sections of a yacc grammar file: declarations, rules, and programs. %{ #include <stdio.h> int regs[26]; int base; %} %start list %union { int a; } %type <a> expr number %token DIGIT LETTER %left '|' %left '&' %left '+' '-' %left '*' '/' '%' %left UMINUS %% list: | list stat '\n' | list error '\n' { yyerrok; } ; /*supplies precedence for unary minus */ /* beginning of rules section */ /*empty */
stat:
regs[$1] = $3; } ; expr: '(' expr ')' { $$ = $2; } | expr '*' expr { $$ = $1 * $3; } | expr '/' expr { $$ = $1 / $3; } | expr '%' expr { $$ = $1 % $3; } | expr '+' expr { $$ = $1 + $3; } | expr '-' expr { $$ = $1 - $3; } | expr '&' expr
{ $$ = $1 & $3; } | expr '|' expr { $$ = $1 | $3; } | '-' expr %prec UMINUS { $$ = -$2; } | LETTER { $$ = regs[$1]; }
%%
main() { return(yyparse()); }
yywrap() { return(1); }
if (accept(oddsym)) { expression(); } else { expression(); if (sym == eql || sym == neq || sym == lss || sym == leq || sym == gtr || sym == geq) { getsym(); expression(); } else { error("condition: invalid operator"); getsym(); } } } void statement(void) { if (accept(ident)) { expect(becomes); expression(); } else if (accept(callsym)) { expect(ident); } else if (accept(beginsym)) { do { statement(); } while (accept(semicolon)); expect(endsym); } else if (accept(ifsym)) { condition(); expect(thensym); statement(); } else if (accept(whilesym)) { condition(); expect(dosym); statement(); } } void block(void) { if (accept(constsym)) { do { expect(ident); expect(eql); expect(number); } while (accept(comma)); expect(semicolon); } if (accept(varsym)) { do { expect(ident); } while (accept(comma)); expect(semicolon); } while (accept(procsym)) { expect(ident); expect(semicolon); block(); expect(semicolon); } statement(); }