我如何使用这个makefile生成我的抽象树?为什么我只在1行看到一个错误?

问题描述 投票:1回答:1

def.h

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



typedef enum 
{
  NPROGRAM,
  NVARDECLLIST,
  NFUNCDECLLIST,
  NVARDECL,
  NIDLIST,
  NOPTPARAMLIST,
  NSTATLIST,
  NASSIGNSTAT,
  NWHILESTAT,
  NIFSTAT,
  NFORSTAT,
  NRELEXPR,
  NRETURNSTAT,
  NREADSTAT,
  NLOGICEXPR,
  NWRITESTAT,
  NNEGEXPR,
  NFUNCCALL,
  NEXPRLIST,
  NCONDEXPR,
  NPARAMDECL,
  NMATHEXPR,
  NCASTING
} Nonterminal;


typedef enum
{
  T_BREAK,
  T_TYPE,
  T_BOOLEAN,
  T_INTCONST,
  T_REALCONST,
  T_BOOLCONST,
  T_WRITEOP,
  T_STRCONST,
  T_ID,
  T_NONTERMINAL
} Typenode;


typedef union
{
  int ival;
  float rval;
  char *sval;
  enum {FALSE, TRUE} bval;
} Value;

typedef struct snode
{
  Typenode type;
  Value value;
  struct snode *p1, *p2, *p3;
} Node;

typedef Node *Pnode;


char *newstring(char*);

int yylex();

Pnode nontermnode(Nonterminal, int),
      ntn(Nonterminal),
      idnode(), 
      keynode(Typenode, int), 
      intconstnode(),
      realconstnode(),
      strconstnode(),
      boolconstnode(),
      newnode(Typenode);


void yyerror(),
     treeprint(Pnode, int);

lexer.lex

%{ 
#include "parser.h"                                                             
#include "def.h"
int line = 1;                                                   
Value lexval;
%}                                                              
%option noyywrap

spacing     ([ \t])+
commento    "#"(.)*\n
letter      [A-Za-z]
digit       [0­9]
intconst    {digit}+
strconst    \"([^\"])*\"
boolconst   false|true
realconst   {intconst}\.{digit}+
id          {letter}({letter}|{digit})*
sugar       [ \( \) : , ; \. \+ \- \* / ]
%%
{spacing}   ;
\n          {line++;}
integer     {return(INTEGER);} 
string      {return(STRING);}
boolean     {return(BOOLEAN);}
real        {return(REAL);}
void        {return(VOID);}
func        {return(FUNC);}
body        {return(BODY);}     
end         {return(END);}
else        {return(ELSE);}
while       {return(WHILE);}
do          {return(DO);}
for         {return(FOR);}
to          {return(TO);}
return      {return(RETURN);}
read        {return(READ);}
write       {return(WRITE);}
writeln     {return(WRITELN);}
and         {return(AND);}
or          {return(OR);}
not         {return(NOT);}
if          {return(IF);}
then        {return(THEN);}
break       {return(BREAK);}    
"<="        {return(LEQ);}
">="        {return(GEQ);}  
"!="        {return(NEQ);}
"=="        {return(EQU);}
"<"         {return(LT);}
">"         {return(GT);}
{intconst}  {lexval.ival = atoi(yytext); return(INTCONST);}
{strconst}  {lexval.sval = newstring(yytext); return(STRCONST);}
{boolconst} {lexval.bval = (yytext[0] == 'f' ? FALSE : TRUE); return(BOOLCONST);}
{realconst} {lexval.rval = atof(yytext); return(REALCONST);}
{id}        {lexval.sval = newstring(yytext); return(ID);}
{sugar}     {return(yytext[0]);}
.           {return(ERROR);}
%%
char *newstring(char *s)
{
  char *p;

  p = malloc(strlen(s)+1);
  strcpy(p, s);
  return(p);
}

制作文件

bup: lexer.o parser.o tree.o
    cc -g -o bup lexer.o parser.o tree.o

lexer.o: lexer.c parser.h def.h
    cc -g -c lexer.c 

parser.o: parser.c def.h
    cc -g -c parser.c

tree.o: tree.c def.h
    cc -g -c tree.c

lexer.c: lexer.lex parser.y parser.h parser.c def.h
    flex -o lexer.c lexer.lex

parser.h: parser.y def.h
    bison -vd -o parser.c parser.y

parser.y

%{
#include "def.h"
#define YYSTYPE Pnode
extern char *yytext;
extern Value lexval;
extern int line;
extern FILE *yyin;
Pnode root = NULL;
%}
%token ID FUNC  BODY    END     BREAK   IF  THEN    ELSE    TYPE    WHILE   DO  FOR     RETURN      READ    WRITE   WRITELN
%token      AND     OR  INTCONST    REALCONST   BOOLCONST   STRCONST    INTEGER     REAL    NOT  STRING  BOOLEAN  VOID  PLUS  MINUS  TIMES  SLASH
%token  LEQ  GEQ  NEQ  EQU  GT  LT  TO  ERROR
%%
program         :  var-decl-list func-decl-list body '.'    {root = $$ = ntn(NPROGRAM);
                                                            root->p1 = ntn(NVARDECLLIST);
                                                            root->p2 = ntn(NFUNCDECLLIST);
                                                            root->p1->p1 = $1;
                                                            root->p2->p1 = $2;
                                                            root->p3 = $3;}
                ;

var-decl-list   :  var-decl var-decl-list                   {$$ -> p1=$1;
                                                            $1->p3=$2;}
                |                                           {$$ = NULL;}
                ;

var-decl        :  id-list ':' type ';'                     {$$ = ntn(NVARDECL);
                                                            $$ -> p1 = ntn(NIDLIST);
                                                            $$->p1->p1=$1; $$ -> p1 -> p3 = $3;}
                ;

id-list         : ID {$$ = idnode();} ',' id-list           {$$ = $2;
                                                            $2 -> p3 = $4;} 
                | ID                                        {$$ = idnode();}
                ;

type            : INTEGER                                   {$$ = keynode(T_TYPE, INTEGER);}
                | REAL                                      {$$ = keynode(T_TYPE, REAL);}
                | STRING                                    {$$ = keynode(T_TYPE, STRING);}

                | BOOLEAN                                   {$$ = keynode(T_TYPE, BOOLEAN);}

                | VOID                                      {$$ = keynode(T_TYPE, VOID); }

                ;

func-decl-list  : func-decl func-decl-list                  {$$ -> p1 = $1;
                                                            $1 -> p3 = $2;}
                |                                           {$$ = NULL;}
                ;

func-decl       : FUNC ID {$$ = idnode();} '(' opt-param-list ')' ':' type var-decl-list body ';'       {$$ -> p1 = $3;
                                                                                                        $$ -> p2 = ntn(NOPTPARAMLIST);
                                                                                                        $$ -> p2 ->p1=$5;
                                                                                                        $$ -> p2 -> p3 = $8;
                                                                                                        $$ -> p2 -> p3->p3 = ntn(NVARDECLLIST);
                                                                                                        $$ -> p2 -> p3->p3->p1 = $9;
                                                                                                        $$ -> p2 -> p3->p3->p3 = $10;} 
                ;

opt-param-list  : param-list                                {$$ = $1;}
                |                                           {$$ = NULL;}
                ;

param-list      : param-decl ',' param-list                 {$$ = $1;
                                                            $1 -> p3 = $3;}
                | param-decl                                
                ;

param-decl      : ID {$$ = idnode();} ':' type              {$$=ntn(NPARAMDECL);
                                                            $$ -> p1 = $2;
                                                            $$ -> p2 = $4;}
                ;

body            : BODY stat-list END                        {$$ = ntn(NSTATLIST);
                                                            $$->p1=$2;}
                ;

stat-list       : stat ';' stat-list                        {$$ = $1;
                                                            $1 -> p3 = $3;}
                | stat  ';'                                 {$$=$1;}
                ;
stat            : assign-stat                               
                | if-stat                                   
                | while-stat                                
                | for-stat                                  
                | return-stat                               
                | read-stat                                 
                | write-stat                                
                | func-call                                 
                | BREAK                                     {$$ = newnode(T_BREAK);}
                ;

assign-stat     : ID {$$ = idnode();} '=' expr              {$$ = ntn(NASSIGNSTAT);
                                                            $$ -> p1 = $2;
                                                            $$ -> p2 = $4;}
                ;

if-stat         : IF expr THEN stat-list opt-else-stat END  {$$ = ntn(NIFSTAT);
                                                            $$ -> p1 = $2;
                                                            $$ -> p2 = ntn(NSTATLIST);
                                                            $$ ->p2 -> p3 = $5;}
                ;

opt-else-stat   : ELSE stat-list                            {$$ = ntn(NSTATLIST);
                                                            $$->p1=$2;}
                |                                           {$$ = NULL;}
                ;

while-stat      : WHILE expr DO stat-list END               {$$ = ntn(NWHILESTAT);
                                                            $$->p1=$2;
                                                            $$->p2=ntn(NSTATLIST);
                                                            $$->p2->p1=$4;}
                ;       

for-stat        : FOR ID {$$=idnode();} '=' expr TO expr DO stat-list END   {$$ = ntn(NFORSTAT);
                                                                            $$->p1=$3;
                                                                            $$->p2=$5;
                                                                            $$->p2->p3=$7;
                                                                            $$->p2->p3->p3=ntn(NSTATLIST);
                                                                            $$->p2->p3->p3->p1=$9;}
                ;

return-stat     : RETURN opt-expr                           {$$ = ntn(NRETURNSTAT);
                                                            $$->p1=$2;}
                ;

opt-expr        : expr                                      {$$=$1;}
                |                                           {$$=NULL;}
                ;

read-stat       : READ '(' id-list ')'                      {$$ = ntn(NREADSTAT);
                                                            $$->p1=ntn(NIDLIST);
                                                            $$->p1->p1=$3;}
                ;

write-stat      : write-op '(' expr-list ')'                {$$ = ntn(NWRITESTAT);
                                                            $$->p1=$1;
                                                            $$->p2=ntn(NEXPRLIST);
                                                            $$->p2->p1=$3;}
                ;

write-op        : WRITE                                     {$$ = keynode(T_WRITEOP, WRITE);}

                | WRITELN                                   {$$ = keynode(T_WRITEOP, WRITELN);}

                ;

expr-list       : expr ',' expr-list                        {$$=$1;
                                                            $1->p3=$3;}
                | expr
                ;

expr            : expr logic-op bool-term                   { $$=$2;
                                                            $2->p1=$1;
                                                            $2->p2=$3;}
                | bool-term                                 
                ;

logic-op        : AND                                       {$$=nontermnode(NLOGICEXPR, AND);}

                | OR                                        {$$=nontermnode(NLOGICEXPR, OR);}

                ;

bool-term       : rel-term rel-op rel-term                  {$$=$2;
                                                            $2->p1=$1;
                                                            $2->p2=$3;}
                | rel-term
                ;
rel-op          : EQU                                   {$$=nontermnode(NRELEXPR, EQU);}

                | NEQ                                   {$$=nontermnode(NRELEXPR, NEQ);}

                | GT                                        {$$=nontermnode(NRELEXPR, GT);}

                | GEQ                                   {$$=nontermnode(NRELEXPR, GEQ);}

                | LT                                        {$$=nontermnode(NRELEXPR, LT);}

                | LEQ                                   {$$=nontermnode(NRELEXPR, LEQ);}

                ;
rel-term        : rel-term low-prec-op low-term             {$$=$2;
                                                            $2->p1=$1;
                                                            $2->p2=$3;}
                | low-term
                ;

low-prec-op     : PLUS                                      {$$=nontermnode(NMATHEXPR, PLUS);}

                | MINUS                                     {$$=nontermnode(NMATHEXPR, MINUS);}

                ;   

low-term        : low-term high-prec-op factor              {$$=$2;
                                                            $2->p1=$1;
                                                            $2->p2=$3;}
                | factor
                ;

high-prec-op    : TIMES                                         {$$=nontermnode(NMATHEXPR, TIMES);}

                | SLASH                                     {$$=nontermnode(NMATHEXPR, SLASH);}

                ;

factor          : unary-op factor                           {$$=$1;
                                                            $1->p3=$2;}
                | '(' expr ')'                              {$$=$2;}
                | ID                                        {$$=idnode();}
                | const                                     {$$=$1;}
                | func-call                                 {$$=$1;}
                | cond-expr                                 {$$=$1;}
                | cast '(' expr ')'                         {$$=$1;
                                                            $1->p3=$3;}
                ;

unary-op        : MINUS                                         {$$=nontermnode(NNEGEXPR, MINUS);}

                | NOT                                       {$$=nontermnode(NNEGEXPR, NOT);}

                ;   

const           : INTCONST                                  {$$=intconstnode();}
                | REALCONST                                 {$$=realconstnode();}
                | STRCONST                                  {$$=strconstnode();}
                | BOOLCONST                                 {$$=boolconstnode();}
                ;

func-call       : ID {$$=idnode();} '(' opt-expr-list ')'   {$$ = ntn(NFUNCCALL);
                                                            $$->p1=$2; $$->p2=$4;}
                ;

opt-expr-list   : expr-list                                 {$$=ntn(NEXPRLIST); $$->p1=$1;}
                |                                           {$$=NULL;}
                ;

cond-expr       : IF expr THEN expr ELSE expr END           {$$=ntn(NCONDEXPR);
                                                            $$->p1=$2;
                                                            $$->p2=$4;
                                                            $$->p3=$6;}
                ;

cast            : INTEGER                                   {$$=nontermnode(NCASTING,INTEGER);}

                | REAL                                      {$$=nontermnode(NCASTING, REAL);}

                ;
%%      

Pnode ntn(Nonterminal nonterm)
{
    Pnode p = newnode(T_NONTERMINAL);
    p->value.rval = nonterm;
    return(p);
}

Pnode nontermnode(Nonterminal nonterm, int valore)
{
    Pnode p = newnode(T_NONTERMINAL);
    p->value.rval = nonterm;
    p->value.ival = valore;
    return(p);
}

Pnode idnode()
{
    Pnode p = newnode(T_ID);
    p->value.sval = lexval.sval;
    return(p);
}

Pnode keynode(Typenode keyword, int valore)
{
    Pnode p = newnode(keyword);
    p->value.ival = valore;
    return p;
}

Pnode intconstnode()
{
    Pnode p = newnode(T_INTCONST);
    p->value.ival = lexval.ival;
    return(p);
}

Pnode realconstnode()
{
    Pnode p = newnode(T_REALCONST);
    p->value.rval = lexval.rval;
    return(p);
}

Pnode strconstnode()
{
    Pnode p = newnode(T_STRCONST);
    p->value.sval = lexval.sval;
    return(p);
}

Pnode boolconstnode()
{
  Pnode p = newnode(T_BOOLCONST);
  p->value.bval = lexval.bval;
  return(p);
}

Pnode newnode(Typenode tnode)
{
  Pnode p = malloc(sizeof(Node));
  p->type = tnode;
  p->p1 = p->p2 = p->p3 = NULL;
  return(p);
}

int main()
{
  int result;
  printf("----------------------------------------------");
  yyin = stdin;
  if((result = yyparse()) == 0)
    treeprint(root, 0);
  return(result);
}

void yyerror()
{
  fprintf(stderr, "Line %d: syntax error on symbol \"%s\"\n",
          line, yytext);
  exit(-1);
}

树.c

#include "def.h"

char* tabtypes[] =
{
  "T_BREAK",
  "T_TYPE",
  "T_BOOLEAN",
  "T_INTCONST",
  "T_REALCONST",
  "T_BOOLCONST",
  "T_WRITEOP",
  "T_STRCONST",
  "T_ID",
  "T_NONTERMINAL"
};

char* tabnonterm[] =
{
  "PROGRAM",
  "NVARDECLLIST",
  "NFUNCDECLLIST",
  "NVARDECL",
  "NIDLIST",
  "NOPTPARAMLIST",
  "NSTATLIST",
  "NASSIGNSTAT",
  "NWHILESTAT",
  "NIFSTAT",
  "NFORSTAT",
  "NRELEXPR",
  "NRETURNSTAT",
  "NREADSTAT",
  "NLOGICEXPR",
  "NWRITESTAT",
  "NNEGEXPR",
  "NFUNCCALL",
  "NEXPRLIST",
  "NCONDEXPR",
  "NPARAMDECL",
  "NMATHEXPR",
  "NCASTING"
};

void treeprint(Pnode root, int indent)
{

  int i;
  Pnode p;

  for(i=0; i<indent; i++)
    printf("    ");
  printf("%s", (root->type == T_NONTERMINAL ? tabnonterm[root->value.ival] : tabtypes[root->type]));
  if(root->type == T_ID || root->type == T_STRCONST)
    printf(" (%s)", root->value.sval);
  else if(root->type == T_INTCONST)
    printf(" (%d)", root->value.ival);
  else if(root->type == T_BOOLCONST)
    printf(" (%s)", (root->value.ival == TRUE ? "true" : "false"));
  printf("\n");
  for(p=root->p1; p != NULL; p = p->p3)
    treeprint(p, indent+1);
}

prog ( 包含语法示例的文件)

numero: integer;
func fattoriale(n: integer): integer
  fact: integer;
body
  if n == 0 then
    fact = 1;
  else
    fact = n * fattoriale(n­1);
  end;
  return fact;
end;
func stampaFattoriali(tot: integer): void
  i, f: integer;
body
  for i=0 to tot do
    f = fattoriale(i);
    writeln("Il fattoriale di ", i, "è ", f);
  end;
end;
body
  read(numero);
  if numero < 0 then
    writeln("Il numero ", numero, "non è valido");
  else
    stampaFattoriali(numero);
end.

当我在终端机上输入make时,它创建的文件有:tree.o parser.o parser.h parser.c lexer.c lexer.o bup。

当我执行bup文件时,终端显示了这个错误信息。

"ine 1: syntax error on symbol "

所以它没有生成抽象树。

我不知道这个错误是指prog还是lexer.lex或者parse.y文件。

makefile yacc lex
1个回答
0
投票

Yaccbison为终端标记分配了自己的数字,并假定词典将使用这些数字。但你在 def.h 头,而yaccbison对此一无所知。它不会正确解释由 yylex 这将使其无法正确解析。

所以不要这样做。

让 bison 生成令牌代码,使用它生成的头文件 (parser.h 与你的设置),不要踩着它的脚,自己去定义枚举值。

关于调试的提示,在你开始调试之前,你写的代码真的太多了,你在问题结尾处抱怨不知道从哪里找错误,正好说明了这个事实。与其写下整个项目,然后希望它能作为一个整体工作,不如写下一些小片段,然后边走边调试。虽然你需要解析器来生成令牌类型值,但你不需要运行解析器来测试你的扫描器。您可以编写一个简单的程序,重复调用 yylex 并打印返回的类型和值。(或者你也可以直接用 -d 命令行选项,这就更简单了)。)

同样,你应该能够通过编写一些测试函数来测试你的AST方法,这些函数使用这些方法来构建、行走和打印出一个AST。确保它们能产生预期的结果。

只有当你有证据表明词典产生了正确的标记,并且你的AST构造函数工作时,你才应该开始调试你的解析器。同样地,如果你使用内置的调试工具,你会发现这要容易得多;请参见 调试你的解析器 在拜辛手册的章节中获取说明。

好运。

© www.soinside.com 2019 - 2024. All rights reserved.