Compilation yacc和lex中的yytext累积问题
我试图打印AST并在树中打印标识符的实际名称。 我用的是lex和yacc 出于某种原因,yacc会将所有标记提前读取到一行中,直到“;”这会阻止我使用yytext访问标识符的文本值 这是lex文件:Compilation yacc和lex中的yytext累积问题,compilation,abstract-syntax-tree,yacc,lex,preorder,Compilation,Abstract Syntax Tree,Yacc,Lex,Preorder,我试图打印AST并在树中打印标识符的实际名称。 我用的是lex和yacc 出于某种原因,yacc会将所有标记提前读取到一行中,直到“;”这会阻止我使用yytext访问标识符的文本值 这是lex文件: %{ %} %% "&&" {return OP_AND;} \"|"\"|" {return OP_OR;} != {return OP_NE;} == {return OP_EQ;} > {return OP_GT;
%{
%}
%%
"&&" {return OP_AND;}
\"|"\"|" {return OP_OR;}
!= {return OP_NE;}
== {return OP_EQ;}
> {return OP_GT;}
>= {return OP_GE;}
\< {return OP_LT;}
\<= {return OP_LE;}
! {return OP_NOT;}
= {return ASSIGN;}
\+ {return PLUS;}
\- {return MINUS;}
\* {return MULT;}
\/ {return DIV;}
\& {return ADRS;}
\^ {return PTR_VAL;}
\; {return SEMI;}
, {return COMMA;}
\{ {return CURLY_O;}
\} {return CURLY_C;}
\( {return PAREN_O;}
\) {return PAREN_C;}
\| {return BAR;}
\[ {return SQR_O;}
\] {return SQR_C;}
else {return ELSE;}
if {return IF;}
do {return DO;}
for {return FOR;}
bool {return BOOL;}
void {return VOID;}
int { return INT;}
charp {return CHARP;}
intp {return INTP;}
string {return STRING;}
while {return WHILE;}
true {return TRUE_;}
false {return FALSE_;}
return {return RETURN;}
null {return NULL_;}
0|[1-9][0-9]* {return CONST_INT;}
[a-zA-Z][a-zA-Z0-9]* { return IDENT;}
\'.\' {return CONST_CHAR; }
\".*\" {return CONST_STRING; }
\[\$([^\$]*\$+[^\]])*[^\$]*\$+\] { /*comment*/}
[ \n\t] { /* skip whitespace */}
. {return ILLEAGAL;}
%%
void main(int x){
int y,w,r; int z;
}
FUNC
void
main
int x
x
BODY
DECL
int z;
;
DECL
int y,w,r;
,
;
,
,
,
FUNC
void
main
int
x
BODY
DECL
int
z
DECL
int
,
y
,
w
r
这是预订单中的输出AST:
%{
%}
%%
"&&" {return OP_AND;}
\"|"\"|" {return OP_OR;}
!= {return OP_NE;}
== {return OP_EQ;}
> {return OP_GT;}
>= {return OP_GE;}
\< {return OP_LT;}
\<= {return OP_LE;}
! {return OP_NOT;}
= {return ASSIGN;}
\+ {return PLUS;}
\- {return MINUS;}
\* {return MULT;}
\/ {return DIV;}
\& {return ADRS;}
\^ {return PTR_VAL;}
\; {return SEMI;}
, {return COMMA;}
\{ {return CURLY_O;}
\} {return CURLY_C;}
\( {return PAREN_O;}
\) {return PAREN_C;}
\| {return BAR;}
\[ {return SQR_O;}
\] {return SQR_C;}
else {return ELSE;}
if {return IF;}
do {return DO;}
for {return FOR;}
bool {return BOOL;}
void {return VOID;}
int { return INT;}
charp {return CHARP;}
intp {return INTP;}
string {return STRING;}
while {return WHILE;}
true {return TRUE_;}
false {return FALSE_;}
return {return RETURN;}
null {return NULL_;}
0|[1-9][0-9]* {return CONST_INT;}
[a-zA-Z][a-zA-Z0-9]* { return IDENT;}
\'.\' {return CONST_CHAR; }
\".*\" {return CONST_STRING; }
\[\$([^\$]*\$+[^\]])*[^\$]*\$+\] { /*comment*/}
[ \n\t] { /* skip whitespace */}
. {return ILLEAGAL;}
%%
void main(int x){
int y,w,r; int z;
}
FUNC
void
main
int x
x
BODY
DECL
int z;
;
DECL
int y,w,r;
,
;
,
,
,
FUNC
void
main
int
x
BODY
DECL
int
z
DECL
int
,
y
,
w
r
我期望的输出:
%{
%}
%%
"&&" {return OP_AND;}
\"|"\"|" {return OP_OR;}
!= {return OP_NE;}
== {return OP_EQ;}
> {return OP_GT;}
>= {return OP_GE;}
\< {return OP_LT;}
\<= {return OP_LE;}
! {return OP_NOT;}
= {return ASSIGN;}
\+ {return PLUS;}
\- {return MINUS;}
\* {return MULT;}
\/ {return DIV;}
\& {return ADRS;}
\^ {return PTR_VAL;}
\; {return SEMI;}
, {return COMMA;}
\{ {return CURLY_O;}
\} {return CURLY_C;}
\( {return PAREN_O;}
\) {return PAREN_C;}
\| {return BAR;}
\[ {return SQR_O;}
\] {return SQR_C;}
else {return ELSE;}
if {return IF;}
do {return DO;}
for {return FOR;}
bool {return BOOL;}
void {return VOID;}
int { return INT;}
charp {return CHARP;}
intp {return INTP;}
string {return STRING;}
while {return WHILE;}
true {return TRUE_;}
false {return FALSE_;}
return {return RETURN;}
null {return NULL_;}
0|[1-9][0-9]* {return CONST_INT;}
[a-zA-Z][a-zA-Z0-9]* { return IDENT;}
\'.\' {return CONST_CHAR; }
\".*\" {return CONST_STRING; }
\[\$([^\$]*\$+[^\]])*[^\$]*\$+\] { /*comment*/}
[ \n\t] { /* skip whitespace */}
. {return ILLEAGAL;}
%%
void main(int x){
int y,w,r; int z;
}
FUNC
void
main
int x
x
BODY
DECL
int z;
;
DECL
int y,w,r;
,
;
,
,
,
FUNC
void
main
int
x
BODY
DECL
int
z
DECL
int
,
y
,
w
r
当我进入规则:在我的yacc文件中键入yytext时,可以看到它包含整个句子(“int y,w,r;”而不是“int”),当我进入规则:id时,它只包含一个令牌,恰好是一个令牌,然后是预期的令牌。-请注意,在函数名和函数参数中,文本可以正常工作
-我尝试从lex文件打印yytext,标记似乎包含正确的值。
yytext
指向扫描的最后一个lexeme。以前保存到扫描仪intrrnal缓冲区中的任何其他指针(例如以前的值yytext
)无效,不能假定X指向任何有用的东西
在解析器操作中,您几乎不知道最后扫描的标记是什么。Yacc/bison生成LALR(1)解析器,其中1
表示“一个前瞻令牌”。这意味着解析器(可以)始终检查下一个标记,如果它这样做,则标记yytext
将指向。有些实现总是提前阅读;其他人,如bison,如果前瞻不会改变解析器的行为,则有时不进行前瞻性阅读。因此,在解析器操作期间,哪个标记yytext
指向哪个标记是未指定的,并且可能在将来的版本中或使用不同的实现进行更改
底线:千万不要在解析器操作中使用yytext
。不要将yytext
的指针值从扫描仪传递到解析器。如果您需要解析器中令牌的字符串值,请复制该字符串并通过yylval
将副本的地址传递给解析器。如果您使用了strdup
或类似工具,请不要忘记在不再需要副本时释放副本