【发布时间】:2020-07-28 15:36:44
【问题描述】:
好的,所以我正在尝试使用一个解析器来尝试一种...实验性语言。
主要思想是这样的:
this is a command
this is [another] command
应该输出这个:
push: command
push: a
push: is
push: this
push: command
<start:inline>
push: another
<end:inline>
push: is
push: this
这是我的词法分析器:
%option noyywrap
%{
#include <stdio.h>
#define YY_DECL int yylex()
#include "parser3.tab.h"
%}
%%
":" { return COLON; }
,(\n+)? { return COMMA; }
\[ { return INLINE_START; }
\] { return INLINE_END; }
\{ { return DEFERRED_START; }
\}? { return DEFERRED_END; }
\n|\| { return NL; }
[ \t]+ { }
[a-zA-Z0-9!@#$%^&\*\-\+\/\\\"\'\(\)]+ { yylval.str=strdup(yytext); return ID; }
%%
这是我的解析器:
%{
#include <stdio.h>
#include <stdlib.h>
extern int yylex();
extern int yyparse();
extern FILE* yyin;
void yyerror(const char* s);
%}
%union {
char* str;
}
%token NL
%token <str> ID
%token COLON
%token BAR
%token COMMA
%token <str> INLINE_START INLINE_END
%token <str> DEFERRED_START DEFERRED_END
%type <str> argument
%type <str> block_start block_end
/****************************************
Options
****************************************/
%glr-parser
%define parse.error verbose
%locations
%start program
%%
block_start : INLINE_START { printf("<start:inline>\n"); }
| DEFERRED_START { printf("found START\n"); }
;
block_end : INLINE_END { printf("<end:inline>\n"); }
| DEFERRED_END { printf("found END\n"); }
;
block : block_start statement_list block_end { /*printf("found block\n");*/ }
;
argument : ID
| block { $$ = ""; }
| COMMA { $$ = ""; }
;
command : argument { if (strcmp($argument,"")) printf(" push: \033[1;36m%s\033[0m\n", $argument); }
| argument command { if (strcmp($argument,"")) printf(" push: \033[1;36m%s\033[0m\n", $argument); }
;
label : ID COLON command { printf("> store: \033[1;36m%s\033[0m\n", $ID); }
;
statement_separator : NL
;
statement : command
| label
;
statement_list : statement
| statement_list statement_separator statement
| statement_list statement_separator
;
program : statement_list
;
%%
int main(int argc, char** argv) {
yyin = fopen(argv[1],"r");
printf("parsing: %s\n",argv[1]);
do {
yyparse();
} while(!feof(yyin));
return 0;
}
void yyerror(const char* s) {
fprintf(stderr, "Parse error: %s\n", s);
exit(1);
}
目前的输出是:
parsing: test6.art
push: command
push: a
push: is
push: this
<start:inline>
push: another
<end:inline>
push: command
push: is
push: this
有什么想法可以强制它在最后一个命令中首先看到“command”和“is”标记(按此特定顺序),然后再看到块?
【问题讨论】:
-
因为你包含了你的词法分析器,所以有几个快速说明:(1)
,(\n+)?与.\n*完全相同(或者,就此而言,.\n+?,但这可能会使那些认为非贪婪匹配是可能的。)(2)\}?中的?毫无意义,因为 (f)lex 永远不会匹配零长度标记。 (反斜杠也是不必要的,因为}不是元字符。它仅用于终止以{开头的内容,无论是宏还是重复。但它不会造成任何伤害,并且可以认为它更具可读性。)我正在努力回答您的实际问题。 -
请不要再重新创建burninanted
flextag。 flex 词法分析器有一个专用标签,您可以使用它来代替。
标签: c parsing bison flex-lexer yacc