Little Languages with Lex, Yacc, and MFC
by Jason Shankel


Example 1:
CRichEditCntrItem *CreateClientItem(_reobject *)const
{
    return NULL;
}

Example 2:
void CSlideDoc::Serialize(CArchive& ar)
{
 CRichEditDoc::Serialize(ar);
}

Example 3:
void CSlideView::OnCompile()
{
 CString compileString = "";  
 EDITSTREAM es = {reinterpret_cast<DWORD>(&compileString), 0, 
                                     SlideViewEditStreamCallBack};
 GetRichEditCtrl().StreamOut(SF_TEXT, es);
}   

Example 4:
Add SlideMessage to SlideView.cpp:
extern "C" 
void SlideMessage(char *message)
{
 AfxMessageBox(message);
}


Listing One
/* This callback is used by CSlideView's rich text edit control to stream text
into a CString 
dwCookie - pointer to a CString
pbBuff - pointer to text
cb - size of pbBuff
pcb - gets number of bytes copied
*/
static DWORD CALLBACK 
SlideViewEditStreamCallBack(
 DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
{
 CString *compileString = reinterpret_cast<CString *>(dwCookie);
 for (int i=0;i<cb;i++)
  (*compileString) += static_cast<char>(pbBuff[i]);
 *pcb = cb;
 return 0;
}

Listing Two 
%{
/* This bison file implements the grammar rules for recognizing a 
sequence of comma-delimited strings
*/
void SlideMessage(char *message);
void yyerror(char *);
int yylex(void);
%}

%token TOKEN
%%

start: /*empty*/
 | little_list {SlideMessage("Stringlist Found");}
;
little_list : TOKEN 
 | little_list ',' TOKEN 
;
%%

Listing Three 
%{
/* This flex file implements the rules for tokenizing strings */
#include "slpars_t.h"
#include <stdlib.h>
#include <string.h>

/* Redefine input source (see article) */
int SlideYYInput(char *buf,int max_size);
#undef YY_INPUT
#define YY_INPUT(buf,result,max_size) \
 (result = SlideYYInput(buf,max_size))
%}
%%
[A-z][A-z0-9]* { return TOKEN;};
[ \t\n] {/*ignore whitespace*/};
 . {return yytext[0];};
%%
void SlideMessage(char *message);
int yyparse();
static char *SlideInputStream;

/* yywrap and yyerror are required by flex and bison */
void yyerror(char *err)
{
 SlideMessage(err);
}
int yywrap()
{
 return 1;
}
/* YY_INPUT redirects lex to get its input from this function.  
It just copies data from a local static char * assigned in SlideCompile.
*/
int SlideYYInput(char *buf,int max_size)
{
 int n = min(max_size,(int)strlen(SlideInputStream));
 if (n > 0)
 {
  memcpy(buf,SlideInputStream,n);
  SlideInputStream += n;
 }
 return n;
}
/* SlideCompile runs the compiler. Called from OnCompile in CSlideView */
void SlideCompile(char *inputStream)
{
 SlideInputStream = inputStream;
 yyrestart(0);
 yyparse();
}

Listing 4
/* OnCompile streams text from the rich edit control into a local CString and 
sends the CString to SlideCompile for processing by lex and yacc
*/
extern "C" 
void SlideCompile(char *inputStream);
void CSlideView::OnCompile() 
{
 CString compileString = "";
 EDITSTREAM es = 
  {reinterpret_cast<DWORD>(&compileString), 0, SlideViewEditStreamCallBack};
 GetRichEditCtrl().StreamOut(SF_TEXT, es);  
 if (es.dwError == 0)
 {
  SlideCompile(const_cast<char *>(LPCTSTR(compileString)));
 }
}


4


