Lex&Yacc Introduction
Table of Contents
1 Introduction
Lex is a lexical analyzer and is used to break up the input stream into useful elements, and Yacc(also stands for Yet Another Compiler Compiler), given a grammar, generates a parser for it. When both tools are properly used, these tools allow you to parse complex languages and configure file with ease, just as the following example.
2 An example
here we use lex and yacc to parse the following configure file, you can find that it is so convenient to parse a configure file with these tools.
2.1 Configure File
2.2 Lex source file
%{ #include <stdlib.h> #include "y.tab.h" void yyerror(char *); %} %% \[[^\n]+\] { yylval.string = yytext; return ATCMD; } \"[^\n\"]+\" { yylval.string = yytext; return RESULT_CODE; } [\[\]] { return *yytext; } \#[^\n]* ; /* ignore comment line */ [ \t\n]+ ; /* ignore whitespace */ . yyerror("Unknown character"); %% int yywrap(void) { return 1; }
2.3 Yacc source file
%{ #include <stdio.h> #include <stdlib.h> #include <stdarg.h> /* prototypes */ int yylex(void); void yyerror(char *s); extern FILE *yyin; %} %union { int number; /* integer value */ char *string; /* string value */ } %token <number> NUMBER %token <string> STRING %token ATCMD RESULT_CODE %% parameters: | parameters parameter ; parameter: atcmd | result_code ; atcmd: ATCMD { printf("%s\n", yylval.string); } ; result_code: RESULT_CODE {printf("%s\n", yylval.string);} ; %% void yyerror(char *s) { fprintf(stdout, "%s\n", s); } int main(int argc, char **argv) { if (argc > 1) { yyin = fopen(argv[1], "r"); } else { fprintf(stdout, "Usage: config <file_path>\n"); return -1; } if (yyin == NULL) { fprintf(stdout, "Error: file open error...\n"); return -1; } yyparse(); fclose(yyin); return 0; }
3 Build&Run