我的文件将由我的解析器读取:
的test.txt
BEGINING.
XXX XY-1.
XXXX Y.
XXXX Z.
BODY.
PRINT "Please enter a number?".
END.
PRINT
令牌周围发生错误。在我的词法分析器中,字符串"Please enter a number?"
正在被正确处理,我知道这是因为我将它输出到控制台。
lexer.I
%{
#include <stdio.h>
#include "parser.tab.h"
#define YYSTYPE char *
%}
%option noyywrap
%option caseless
%%
(?i:BEGINING) return TERM_BEGINING;
(?i:BODY) return TERM_BODY;
(?i:END) return TERM_END;
(?i:MOVE) return TERM_MOVE;
(?i:TO) return TERM_TO;
(?i:ADD) return TERM_ADD;
(?i:INPUT) return TERM_INPUT;
(?i:PRINT) return TERM_PRINT;
[\t| ]+ // ignore whitespaces
\n // Ignore new line
[X]+ yylval.integer = yyleng; return TERM_SIZE;
[\"][^"]*[\"] yylval.string = strdup(yytext); printf("%s\n", yytext); return TERM_STR;
";" return TERM_SEPARATOR;
"." return TERM_FULLSTOP;
[0-9]+ yylval.integer = atoi(yytext); return TERM_INT;
[\_\-0-9][a-zA-Z][a-zA-Z0-9\-\_]* yylval.string = strdup(yytext); return TERM_INVALID_VARIABLE_NAME;
[A-Z][A-Z0-9\-]* yylval.string = strdup(yytext); return TERM_VARIABLE_NAME;
. return TERM_INVALID_TOKEN;
%%
//int main(int argc, char** argv) {
// if (argc != 2) {
// yyin = stdin;
// yylex();
// } else {
// FILE* aFile = fopen(argv[1], "r");
// if (!aFile) {
// printf("Cannot open file!\n");
// return -1;
// } else {
// yyin = aFile;
// yylex();
// fclose(yyin);
// }
// }
//}
现在在解析器中,出于调试目的,当从词法分析器返回PRINT
keywor时,我决定打印出单词PRINT
parser.y
%{
//yylval - externalise variable in which yylex should place semantic value associated with a token
//yyparse - parser function produced by bison, call this to start parsing
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <unistd.h>
extern FILE* yyin;
typedef int bool;
#define true 1
#define false 0
//Cause an immediate syntax error
int yyerror(char *s) {
fprintf(stderr, "%s\n", s);
exit(0);
}
//Declare yylex, user supplied lexical analyzer function to get the next token
int yylex(void);
//yywrap text wrap
//When scanner recieves EOF it checks yywrap()
int yywrap(void) {
return 1;
}
// Structure of variable
struct variable {
char* varName;
int varSize;
int varValue;
};
typedef struct {
struct variable* array;
size_t used;
size_t size;
} Array;
// Method declarations
void writeToWarning(char *aWarning);
void writeError(char *anError);
void writeToLog(char *alog);
bool checkIfDeclared(char* varName);
void initialiseArray(Array *a, size_t initialSize);
void insertArray(Array *a, struct variable *aVar);
void freeArray(Array *a);
void createVar(int size, char* varName);
void inputValues(char* varName);
%}
//each token is a terminal
%token TERM_BEGINING TERM_BODY TERM_END TERM_MOVE
TERM_TO TERM_ADD TERM_INPUT TERM_PRINT
TERM_SIZE TERM_STR TERM_SEPARATOR TERM_FULLSTOP
TERM_INT TERM_INVALID_VARIABLE_NAME TERM_VARIABLE_NAME TERM_INVALID_TOKEN
//Everything that something can be
//yyvval array from lexer.l
%union {
int integer;
char* string;
}
//Define anything that the lexer can return as a string or integer
%type<integer> TERM_INT
%type<integer> TERM_SIZE
%type<string> TERM_STR
%type<string> TERM_SEPARATOR
%type<string> TERM_FULLSTOP
%type<string> TERM_VARIABLE_NAME
%type<string> TERM_INVALID_VARIABLE_NAME
%%
// Create grammer
program:
/* empty */ |
begin middle_declarations body grammar_s end {
printf("Parsing complete\n");
exit(0);
};
begin:
TERM_BEGINING TERM_FULLSTOP;
body:
TERM_BODY TERM_FULLSTOP;
end:
TERM_END TERM_FULLSTOP;
middle_declarations:
/* empty */ |
//Left recursive to allow for many declearations
middle_declarations declaration TERM_FULLSTOP;
declaration:
TERM_SIZE TERM_VARIABLE_NAME {
createVar($1, $2);
};
grammar_s:
/* empty */ |
grammar_s grammar TERM_FULLSTOP;
grammar:
add | move | print | input;
add:
TERM_ADD TERM_VARIABLE_NAME TERM_TO TERM_VARIABLE_NAME {
//addVarToVar($2, $4);
}
TERM_ADD TERM_INT TERM_TO TERM_VARIABLE_NAME {
//addNumToVar($2, $4);
}
;
move:
TERM_MOVE TERM_VARIABLE_NAME TERM_TO TERM_VARIABLE_NAME {
//moveVarToVar($2, $4);
}
TERM_MOVE TERM_INT TERM_TO TERM_VARIABLE_NAME {
//moveNumToVar($2, $4);
}
;
print:
TERM_PRINT rest_of_print {
printf("PRINT\n");
};
rest_of_print:
/* empty */ |
rest_of_print other_print;
other_print:
TERM_VARIABLE_NAME {
//printVarName($1);
}
TERM_INVALID_VARIABLE_NAME {
//printInvalidVarName($1);
}
TERM_SEPARATOR {
printf("%s", $1);
}
TERM_STR {
printf("STRING%s%s", $1, "\n");
}
;
input:
// Fullstop declares grammar
TERM_INPUT other_input;
other_input:
/* empty */ |
// Input var1
TERM_VARIABLE_NAME {
inputValues($1);
}
// Can be input var1
TERM_VARIABLE_NAME TERM_SEPARATOR {
//inputValues($2);
}
;
%%
Array a;
void initialiseArray(Array *a, size_t initialSize) {
a->array = (struct variable*) malloc(initialSize * sizeof(struct variable));
a->used = 0;
a->size = initialSize;
}
void insertArray(Array *a, struct variable *aVar) {
if (a->used == a->size) {
a->size *= 6;
a->array = (struct variable*) realloc(a->array, a->size * sizeof(struct variable));
}
a->array[a->used++] = *aVar;
}
void freeArray(Array *a) {
free(a->array);
a->array = NULL;
a->used = a->size = 0;
}
void createVar(int size, char* varName) {
printf("SIZE: %d\n", size);
printf("NAME: %s\n", varName);
bool alreadyDeclared;
alreadyDeclared = checkIfDeclared(varName);
if (!alreadyDeclared) {
struct variable aVar;
aVar.varName = varName;
aVar.varSize = size;
aVar.varValue = 0;
insertArray(&a, &aVar);
writeToLog("Created variable succesfully\n");
} else {
writeToWarning("Variable has already been declared\n");
}
}
bool checkIfDeclared(char* varName) {
for (int i = 0; i < a.used; i++) {
if (strcmp(a.array[i].varName, varName) == 0) {
return 1;
}
}
return 0;
}
void inputValues(char* varName) {
printf("VAR_NAME: %s\n", varName);
}
int main(int argc, char* argv[]) {
if (argc != 2) {
yyin = stdin;
yylex();
} else {
FILE* aFile = fopen(argv[1], "r");
if (!aFile) {
printf("Cannot open file!\n");
return -1;
} else {
int i;
initialiseArray(&a, 5);
yyin = aFile;
yyparse();
}
}
fclose(yyin);
freeArray(&a);
// for (int i = 0; i < 10; i++) {
// struct variable aVar;
// aVar.varName = "TEST_VAR";
// aVar.varSize = 0;
// aVar.varValue = 0;
// insertArray(&a, &aVar);
//}
//for (int j = 0; j < a.used; j++) {
// printf("Name: %s\n", a.array[j].varName);
//}
//printf("Name: %s\n", a.array[9].varName);
//printf("Used: %zu\n", a.used);
//yyparse();
//if (argc > 0) {
// freeArray(&a);
// fclose(yyin);
//}
return 0;
}
void writeToWarning(char *aWarning){
printf("Warning : %s%s", aWarning,"\n");
}
void writeError(char *anError){
printf("Error : %s%s", anError,"\n");
}
void writeToLog(char *alog){
printf("Success : %s%s", alog,"\n");
}
这是我编译的方式
bison -d parser.y -o parser.tab.c
flex -o lexer.yy.c lexer.I
gcc lexer.yy.c parser.tab.c -o parser
这就是我的运作方式
./parser test.txt
然后这是我得到的输出
SIZE: 3 // this is output from the createVar function
NAME: XY-1
Success : Created variable succesfully
SIZE: 4
NAME: Y
Success : Created variable succesfully
SIZE: 4
NAME: Z
Success : Created variable succesfully
"Please enter a number?" // This is output for debugging from the lexer
PRINT // This is output for debugging from the parser,
syntax error
答案 0 :(得分:2)
离开行为(不会改变语法)您的other_print
规则是:
other_print:
TERM_VARIABLE_NAME TERM_INVALID_VARIABLE_NAME TERM_SEPARATOR TERM_STR
输入文件中没有奇怪的终端序列,因此生产不匹配,导致语法错误报告。
你似乎不太可能想要那种语法;我的猜测是你打算将四个终端作为替代而不是连接。如果是这样,您需要将它们与|
s分开。
other_input
也有类似的问题。