考虑为其设计和开发的语言和编译器。
在这种语言中,有一个特定的语句是语法的一部分:(=<identifier>)
。编译器可以识别此部分。但是括号和等号以及标识符之间允许有空格。所以我有这些可能性:
(=<identifier>)
( = <identifier> )
(=identifier )
( =identifier )
...
不考虑整个语法而只考虑处理这种语言特性的规则,我有类似的东西(用于语法规则的类似Bison的语法):
statement: OBRCKT EQ ID CBRCKT
| OBRCKT S EQ S ID S CBRCKT
| OBRCKT S EQ ID S CBRCKT
| OBRCKT S EQ S ID CBRCKT
| OBRCKT S EQ ID CBRCKT
| OBRCKT EQ S ID S CBRCKT
| OBRCKT EQ ID S CBRCKT
| OBRCKT EQ S ID CBRCKT
| ...
空间终端S
可以出现。但是规则的方式,我需要指定所有可能的组合......有没有更好的方法来实现这个结果?
答案 0 :(得分:3)
正如Jim评论的那样,使用你的词汇工具来处理这些案例,而不是将它们写入你的语法产品中。
例如,我通常使用Flex进行词法分析,使用Bison来定义我的语法(可能就像你所做的那样)。
您可以使用以下内容获得您想要的结果(这只是一个示例,因此它非常简单且不能做太多):
lexicalAnalyzer.l
/* lexicalAnalyzer.l
Specifications of tokens for some language.
*/
%{
%}
/*
* Definitions of regular expressions
* Note: You capture whitespace here...
*/
WSPACE [ \t\r]+ //We take care of the spaces here...
/*
* Tokens
*/
%%
"=" {
printf("TOKEN: EQ LEXEME: %s\n", yytext);
return T_EQ;
}
"(" {
printf("TOKEN: OBRCKT LEXEME: %s\n", yytext);
return T_OBRCKT;
}
")" {
printf("TOKEN: CBRCKT LEXEME: %s\n", yytext);
return T_CBRCKT;
}
"<" {
printf("TOKEN: LT LEXEME: %s\n", yytext);
return T_LT;
}
">" {
printf("TOKEN: GT LEXEME: %s\n", yytext);
return T_GT;
}
"identifier" {
printf("TOKEN: IDENT LEXEME: %s\n", yytext);
return T_IDENT;
}
{WSPACE} { }
. {
printf("TOKEN: UNKNOWN LEXEME: %s\n", yytext);
return T_UNKNOWN;
}
%%
syntaxAnalyzer.y
/*
syntaxAnalyzer.y
To create syntax analyzer:
flex file.l
bison file.y
g++ file.tab.c -o file_parser
file_parser < inputFileName
*/
/*
* Declaration section.
*/
%{
#include <stdio.h>
void printRule(const char *lhs, const char *rhs);
int yyerror(const char *s) {
printf("Error!");
}
extern "C" {
int yyparse(void);
int yylex(void);
int yywrap() {return 1;}
}
%}
/*
* Token declarations
*/
%token T_OBRCKT T_CBRCKT
%token T_LT T_GT T_EQ
%token T_IDENT T_UNKNOWN
/*
* Starting point.
*/
%start N_START
/*
* Translation rules.
*/
%%
N_START : N_STATEMENT
{
printRule("START", "STATEMENT");
printf("\n---- Completed parsing ----\n\n");
return 0;
}
;
N_STATEMENT : T_OBRCKT T_EQ T_LT T_IDENT T_GT T_CBRCKT
{
printRule("EXPR", "T_OBRCKT T_EQ T_LT T_IDENT T_GT T_CBRCKT");
}
;
%%
#include "lex.yy.c"
extern FILE *yyin;
void printRule(const char *lhs, const char *rhs) {
printf("%s -> %s\n", lhs, rhs);
return;
}
int main() {
do {
yyparse();
} while (!feof(yyin));
return 0;
}