1

我知道,我们可以在lex中定义一些条件,匹配:</p>

1.<DIRECTIVE>{STRING} {printf("Matching the DIRECTIVE state!");}
2.<REFERENCE>{INTEGER} {printf("Matching the REFERNCE state!");}
3.[\n] {printf("Matching the INITIAL state?");}

4.<*>{DOBULE} {printf("Matching all state include INITIAL? Seem not!");}

如何以正确的方式使用状态?第 3 行和第 4 行的条件有什么不同?

整个.l文件,我剪的,现在只是为了实现一个参考。当我运行它时,它可以很好地工作,但最后总是说“line:4:error:syntax error”,我不知道为什么!我的 test.vm 只有 2 行文本。

%{
/**支持了所有的token,不支持转义和多行注释*/
#include<stdio.h>
#include<string.h>
#include "context.h"
#include "bool.h"
#include "vtl4.tab.h"

extern int yylex();
/**bracket标志*/
int bracket_flag = 0;
/**引用标志*/
int ref_flag = 0;
/**多行注释标记*/
int mul_comment_flag = 0;
%}
%option stack
%option noyywrap yylineno

%x REF
VAR_NAME ([_a-zA-Z]+[a-zA-Z0-9_\-]*)
%%
/**这里去除$#\n防止覆盖状态REF和DIRECTIVE*/
[^$\n#]*? {printf("text:%s\n",yytext);yylval.string = yytext; return CONTENT;}
/**换行单独取出来,还没清楚为什么*/
\n {printf("newLine:%s\n",yytext);yylval.string = yytext; return CONTENT;}

/**添加^$防止只匹配最后一个变量
 例如:&lt;p class="$b">$a $b</p> 只匹配了最后一个$b
 */
[^#$]*?/"$" {BEGIN REF;printf("begin ref text:%s\n",yytext);yylval.string = yytext; return       CONTENT;}

<REF>"$"|"$!"/"{"?{VAR_NAME} {ref_flag++;printf("$:%s\n",yytext);return DOLLAR;}
<REF>"{" {printf("{:%s\n",yytext);return BRACE;}
<DIRECTIVE>"}" {printf("}:%s\n",yytext);return BRACE_CLOSE;}
<REF>{VAR_NAME}/[^0-9A-Za-z_\-] {
    printf("ref name:%s\n",yytext);
    ref_flag--;
    yylval.sym = find_symbol(yytext);
    return ID;
}
<REF>[ /t"="\n] {BEGIN INITIAL; printf("ref end:%s\n",yytext);}
<REF>[}] {printf("}:%s\n",yytext);return BRACE_CLOSE;}

<<EOF>> {printf("lex end:%s\n",yytext);return LEX_EOF;}
%%

整个 .y 文件:

%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bool.h"
#include "parser.h"
#include "context.h"
#include "vtl4.tab.h"

extern FILE * yyin;
extern FILE * yyout;
int yylex();
#define YYDEBUG 1
%}
/*priority level*/
%union {
struct simpleNode *ast;
double d;
int i;
bool b;
char* string;
struct symbol *sym;
}

%token ADD SUB MUL DIV MOD EQUAL PARENTHESIS CLOSE_PARENTHESIS BRACE BRACE_CLOSE  LOGICAL_AND LOGICAL_OR LOGIC_EQUAL LOGICAL_LT LOGICAL_LE LOGICAL_GT LOGICAL_GE LOGICAL_NOT_EQUALS

%token  LEX_EOF

%token <string> CONTENT STRING_LITERAL SINGLE_LINE_COMMENT MULTI_LINE_COMMENT
%token <b> BOOL

%token INTEGER_LITERAL

%token <d> DOUBLE_LITERAL

%token DOLLAR

%token <sym> ID

%token HASH SET PARSE IF ELSE ELSEIF FOREACH IN END

%type <ast> root statements statement reference content

%start root

%%
/*JJTPROCESS*/
root:statements LEX_EOF {printf("yacc root\n");$$ = process($1);}
;

statements
: statement {printf("yacc statements:statement\n"); $$ = $1; }
| statements statement {printf("yacc statements:statements statement\n"); $$ =     add_ybrother($1,$2);}
;

statement
 : reference {printf("yacc statement:ref\n"); $$ = $1;}
| content
;

reference
: DOLLAR ID {printf("yacc ref\n");$$ = reference($2);}
 ;

content
: CONTENT {$$ = text(NULL);}
;

%%
int main(){
printf("BEGIN:\n");
FILE *src;
src = fopen("test.vm","r");
yyin = src;
int result = yyparse();
fclose(src);
return result;
}
4

1 回答 1

1

首先,开始条件不是 Lex 的一个特性。它们是 GNU Flex 的一个特性。

该语法<*>确实被记录为“此规则将在任何状态下无条件触发”的意思。

您可能知道,条件可以是独占的(用 定义%x)或包含的(用 定义%s)。

如果您编写一个没有任何条件的规则,那么它在该INITIAL状态下是活动的,并且在任何包含在内的状态下也是有效的:包含的意思是“没有指定条件的规则将在该状态下是活动的”。

如果当前状态是独占状态,则没有任何条件的规则是不活动的:它排除了没有条件的规则。

语法意味着该<*>规则将在所有状态下激活,包括排他性状态。

如果规则没有<...>条件语法,则意味着该规则将仅在INITIAL状态或包含的状态中激活。

你的解析器仍然有很多错误。请记住,最长匹配规则是在输入中的任何点触发的规则,并且可能会被误解为开始条件不起作用。如果输入是catalog并且某些符合条件的规则想要匹配,那么匹配的规则是否具有 属性cat并不重要。这不是最长的比赛。c<*>

于 2013-06-08T02:02:05.153 回答