实现一个解析器,用于在lex / yacc中用C语言定义一组变量

时间:2016-03-16 11:15:34

标签: yacc lex

我将使用lex / yacc实现解析器的定义 c语言中的变量。例如:

% set gnuplot as graphics toolkit, set custum colormap and create exemplary matrix
graphics_toolkit('gnuplot');
colormap([1 0 0; 0 1 0; 0 0 1]);
A = randi([1 3], 5, 5);

% plot with standard settings
subplot (2, 1, 1);
imagesc(A);
caxis([1 3]);
mycb = colorbar();
set(mycb, 'YTick', [1 2 3], 'YTickLabel', {'red', 'green', 'blue'});

% plot with adjusted tick positions (the way I want the colorbar to look like)
subplot (2, 1, 2);
imagesc(A);
caxis([1 3]);
mycb = colorbar();
set(mycb, 'YTick', [4/3 2 8/3], 'YTickLabel', {'red', 'green', 'blue'});

然后为变量赋值。例如:

int x,y,z;
double a,b;
char c;

我想尝试使用int和double作为开始,这样一旦它工作,我修改并引入char定义和赋值,但是现在我无法用我的代码在一行上定义变量。我尝试的任何时候都会出现语法错误。这是我得到的错误:

x = 2
a=2.5
c = 't'

我希望有人帮助我解决这个问题。

lex文件

edited.lex

double t,y,e;
doublet,ysyntax error

yacc文件 edited.y

%{

#include <ctype.h>
#include<stdio.h>
#include <stdlib.h>
#include <string.h>
/* include YACC symbol encoding */
#include "calc.h"
#include "edited.tab.h"


char varname[256];

%}

%option noyywrap

DIGIT [0-9]+

ID [a-zA-Z][a-zA-Z0-9]*


%%
    symbtbl *ptr; /* local variable */

int|float|double|char                 { ECHO;return DATATYPE; }
[[:space:]]                           /* skip spaces */
{DIGIT}+"."{DIGIT}*|"."{DIGIT}+              {sscanf(yytext,"%lg",&yylval.val); ECHO;return DECIMAL;}


"'"."'"                      {sscanf(yytext,"%c",&yylval.vchar); ECHO;return CHARACTER;}  
"," { return yytext[0];}
";" { return yytext[0];}
{ID}   {strcpy(varname,yytext); yylval.sptr=varname;ECHO; return VAR;}
%%

符号表 utils.c

%{
/* math functions */
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "calc.h"


/* custom data structure definitions */


}*/

%}

/* bison data types for symbols */
%union{
  double val;    /* numeric data */
  char vchar;

   /* reference to variables*/
   symbtbl *sptr;

} 

%start Program


%token <val>DECIMAL
%token <vchar>CHARACTER
%token <sptr> VAR 
%token DATATYPE
%left declaration_list
%type <val> declaration_list 
%type <val> assignment_variable 
%type <val> exp 



%%
 Program                :  Program statement
                        ;

 statement              : vardef
                        | assignment_variable
                        ;
vardef                  :  DATATYPE declaration_list ';'|vardef
                        ;
declaration_list        : VAR {$1->value.var;printf("%s",$1->value.var);}
                        | declaration_list ',' VAR   {$1->value.var;}
                        ;
assignment_variable     : VAR '=' exp ';' {$1->value.var=$3;}                     
                        ;                 


exp                     : DECIMAL     {$$=$1;} 
                        ;                      

/*
 * error message handling
 */3
%%
#include <stdio.h>
#include <ctype.h>
char *p;
yyerror(char *s) {
  printf("%s\n",s);
}

main( argc, argv )
char *argv[];
{
  p = argv[0];

  yyparse();
}

标头文件 calc.h

/*
 * Symbol table management functions
*/

#include <string.h>
#include <stdlib.h>

#include "calc.h"

/* head of symbol table list */
symbtbl *st=NULL;

/* add a symbol to table given name and type */

symbtbl *putsymb(char *name, int type) {
    symbtbl *ptr;
    if((ptr=(symbtbl *)(malloc(sizeof(symbtbl))))==NULL) {
        return(NULL); /* allocation failed */
    }
    ptr->name = strdup(name);
    if(ptr->name==NULL) {
        free(ptr);
        return(NULL); /* allocation failed */
    }
    ptr->type=type;
    ptr->value.var=0;
    /* add to list */
    ptr->next=st;
    st=ptr;
    return ptr;
}

/* get a symbol from table */

symbtbl *getsymb(char *name) {
    symbtbl *ptr;
    /* scan the list for element */
    for(ptr=st;ptr!=NULL;ptr=ptr->next)
        if(!strcmp(ptr->name,name))
           return ptr;

    return(NULL); /* not found */
}

1 个答案:

答案 0 :(得分:0)

我尝试使用bison生成解析器,但是我遇到了一些错误。我按照同样的精神从空白处制定新的规则。 我认为您需要了解堆栈的用途,因为您只使用$$进行一次语义操作。另外我认为“$ 1&gt; value.var;”在语义动作中没有任何意义,因为它不是函数调用或赋值。

这里的代码,我希望可以提供帮助

edited.lex

client = mqtt.Client()
client.connect(address, 1883, 60)

while True:
    data = getdata()
    client.publish("$ahmed/",data,0)
    client.loop(timeout=1.0, max_packets = 1) # what should be the parameters here so it doesn't stop publishing?
    time.sleep(0.2)

edited.y

%{

#include <ctype.h>
#include<stdio.h>
#include <stdlib.h>
#include <string.h>
/* include YACC symbol encoding */
#include "edited.tab.h"


char *varname;
char *strdatatype;

%}

%option noyywrap

DIGIT [0-9]+

ID [a-zA-Z][a-zA-Z0-9]*


%%

int|float|double|char           { strdatatype = strdup(yytext); yylval.str=strdatatype; return DATATYPE; }
[[:space:]]             /* skip spaces

INT (1, 2, 3, ...) | (FLOAT or DOUBLE) 1., 2.3, ... | .12, .23, ... */
{DIGIT}+|{DIGIT}+"."{DIGIT}*|"."{DIGIT}+        {sscanf(yytext,"%lg",&yylval.val); return DECIMAL; }

    /* if you want keep the "'" characters yylval.vchar cannot be char type. "'" are added in the semantic action */
"'"."'"                 { yylval.vchar = yytext[1]; return CHARACTER; }  
"," { return yytext[0];}
";" { return yytext[0];}
"=" { return yytext[0];}
{ID}                    { varname = strdup(yytext); yylval.str=varname; return VAR; }
%%