匹配单个问号的简单 Lex/Yacc 语法错误?
Simple Lex/Yacc syntax error matching a single question mark?
我正在尝试使用 lex/yacc 构建一个计算器,您可以在其中创建无限量的变量,并通过链表在计算中使用它们。
当你键入“?”时,它应该打印出链表的内容,它确实这样做了,除了之后,它给了我一个:syntax error
并结束了我的程序。
计算器的其余部分按预期工作,我是不是遗漏了什么?
示例输出
-bash-4.1$ ./calc
a = 42
b = 21
c = a / b
?
num-syms: 5
PHI => 1.61803
PI => 3.14159
a => 42
b => 21
c => 2
syntax error
-bash-4.1$
sym.h
#ifndef SYMTBL_H
#define SYMTBL_H
struct sym {
int length;
char * name;
double value;
struct sym *prev;
struct sym *next;
};
struct sym * sym_p;
struct sym * sym_lookup(char *);
void sym_inventory();
#endif /* SYMTBL_H */
calc.l
%{
/*#include <math.h> */
#include "y.tab.h"
#include "sym.h"
%}
%%
"?" { sym_inventory(); }
([0-9]+|([0-9]*\.[0-9]+)([eE][+-]?[0-9]+)?) {
yylval.dval = atof(yytext);
return NUMBER;
}
[ \t] ; /* ignore whitespace */
[A-Za-z][A-Za-z0-9]* {
/* return symbol pointer */
yylval.symptr = sym_lookup(yytext);
return NAME;
}
"$" { return 0; }
\n |
. { return yytext[0]; };
%%
int yywrap() { return 1; }
calc.y
%{
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "sym.h"
%}
%union {
double dval;
struct sym * symptr;
}
%token <symptr> NAME
%token <dval> NUMBER
%left '-' '+'
%left '*' '/'
%nonassoc UMINUS
%type <dval> expression
%%
statement_list
: statement '\n'
| statement_list statement '\n'
;
statement
: NAME '=' expression {
char *name = ->name;
if (strcmp(name, "PI") != 0 && strcmp(name, "PHI") != 0) {
->value = ;
} else {
yyerror("assign to const");
}
}
| expression { printf("= %g\n", ); }
;
expression
: expression '+' expression { $$ = + ; }
| expression '-' expression { $$ = - ; }
| expression '*' expression { $$ = * ; }
| expression '/' expression {
if ( == 0) {
yyerror("divide by zero");
} else {
$$ = / ;
}
}
| '-' expression %prec UMINUS { $$ = -; }
| '(' expression ')' { $$ = ; }
| NUMBER
| NAME { $$ = ->value; }
;
%%
struct sym * sym_lookup(char * s)
{
if (sym_p == NULL) {
sym_p = (struct sym *)malloc(sizeof(struct sym));
}
struct sym *original = sym_p;
struct sym * sp = sym_p;
if (sp->name == NULL) {
struct sym *n = (struct sym *)malloc(sizeof(struct sym));
n->name = "PI";
n->value = 3.14159;
n->next = NULL;
sp->name = "PHI";
sp->value = 1.61803;
sp->next = n;
sp->length = 2;
}
while (1) {
if (sp->name == NULL) {
sp->name = strdup(s);
sp->next = NULL;
return sp;
} else if (strcmp(sp->name, s) == 0) {
return sp;
} else if (sp->next != NULL) {
sp = sp->next;
} else {
struct sym *n = (struct sym *)malloc(sizeof(struct sym));
n->name = strdup(s);
sp = original;
struct sym *old = NULL;
while (1) {
if (strcmp(sp->name, s) > 0) {
// new variable name comes before in ascii table
if (old == NULL) {
// new node insert at beginning of sym_p
n->next = original;
n->length = original->length;
sym_p = n;
original = sym_p;
sp = original;
} else {
// insert in middle and update links
old->next = n;
n->next = sp;
sp = original;
}
break;
} else {
if (sp->next != NULL) {
old = sp;
sp = sp->next;
} else {
sp->next = n;
break;
}
}
}
sp = original;
sp->length++;
return n;
}
}
}
void sym_inventory()
{
struct sym * sp = sym_p;
printf("num-syms: %d\n", sp->length);
int i;
int length = sp->length;
for (i = 0; i < length; i++) {
printf("\t%s => %g\n", sp->name, sp->value);
sp = sp->next;
}
}
问题
您的语法无法将空行识别为有效输入。当您键入 ?
后跟一个换行符时,将返回换行符,这在语法上是无效的,因此会出现 'syntax error' 报告。
例如,您可以通过键入 ?a + b
作为输入进行演示。
请注意,您的词法分析器在处理 ?
时并没有让解析器知道它发生了;解析器永远不会看到 ?
.
敦促获得足够的信息来回答问题
Lex 代码的这种改编表明词法分析器将 ?
识别为输入。您的问题没有显示代码的使用方式,因此没有足够的信息让我们知道您做错了什么。您需要提供一个MCVE(Minimal, Complete, Verifiable Example),以便获得相关帮助。
%option noinput
%option nounput
%%
"?" { printf("Got a ?\n"); }
([0-9]+|([0-9]*\.[0-9]+)([eE][+-]?[0-9]+)?) {
printf("Number: %s\n", yytext);
}
[ \t] { printf("Space: [%s]\n", yytext); }
[A-Za-z][A-Za-z0-9]* {
printf("Name: %s\n", yytext);
}
"$" { printf("Dollar\n"); return 0; }
\n |
. { printf("Other: %c\n", yytext[0]); return yytext[0]; };
%%
int yywrap(void) { return 1; }
int main(void)
{
while (yylex() != 0)
;
return 0;
}
示例 运行(shell 提示是 JL:
而不是 $
因为输入之一是 $
):
JL: ./xy73
a b 23
Name: a
Space: [ ]
Name: b
Space: [ ]
Number: 23
Other:
?
Got a ?
Other:
=@%
Other: =
Other: @
Other: %
Other:
$
Dollar
JL:
那个?后跟一个作为字符标记返回的换行符,但您的语法只接受语句后的换行符,该语句始终以 NAME 开头。
我正在尝试使用 lex/yacc 构建一个计算器,您可以在其中创建无限量的变量,并通过链表在计算中使用它们。
当你键入“?”时,它应该打印出链表的内容,它确实这样做了,除了之后,它给了我一个:syntax error
并结束了我的程序。
计算器的其余部分按预期工作,我是不是遗漏了什么?
示例输出
-bash-4.1$ ./calc
a = 42
b = 21
c = a / b
?
num-syms: 5
PHI => 1.61803
PI => 3.14159
a => 42
b => 21
c => 2
syntax error
-bash-4.1$
sym.h
#ifndef SYMTBL_H
#define SYMTBL_H
struct sym {
int length;
char * name;
double value;
struct sym *prev;
struct sym *next;
};
struct sym * sym_p;
struct sym * sym_lookup(char *);
void sym_inventory();
#endif /* SYMTBL_H */
calc.l
%{
/*#include <math.h> */
#include "y.tab.h"
#include "sym.h"
%}
%%
"?" { sym_inventory(); }
([0-9]+|([0-9]*\.[0-9]+)([eE][+-]?[0-9]+)?) {
yylval.dval = atof(yytext);
return NUMBER;
}
[ \t] ; /* ignore whitespace */
[A-Za-z][A-Za-z0-9]* {
/* return symbol pointer */
yylval.symptr = sym_lookup(yytext);
return NAME;
}
"$" { return 0; }
\n |
. { return yytext[0]; };
%%
int yywrap() { return 1; }
calc.y
%{
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "sym.h"
%}
%union {
double dval;
struct sym * symptr;
}
%token <symptr> NAME
%token <dval> NUMBER
%left '-' '+'
%left '*' '/'
%nonassoc UMINUS
%type <dval> expression
%%
statement_list
: statement '\n'
| statement_list statement '\n'
;
statement
: NAME '=' expression {
char *name = ->name;
if (strcmp(name, "PI") != 0 && strcmp(name, "PHI") != 0) {
->value = ;
} else {
yyerror("assign to const");
}
}
| expression { printf("= %g\n", ); }
;
expression
: expression '+' expression { $$ = + ; }
| expression '-' expression { $$ = - ; }
| expression '*' expression { $$ = * ; }
| expression '/' expression {
if ( == 0) {
yyerror("divide by zero");
} else {
$$ = / ;
}
}
| '-' expression %prec UMINUS { $$ = -; }
| '(' expression ')' { $$ = ; }
| NUMBER
| NAME { $$ = ->value; }
;
%%
struct sym * sym_lookup(char * s)
{
if (sym_p == NULL) {
sym_p = (struct sym *)malloc(sizeof(struct sym));
}
struct sym *original = sym_p;
struct sym * sp = sym_p;
if (sp->name == NULL) {
struct sym *n = (struct sym *)malloc(sizeof(struct sym));
n->name = "PI";
n->value = 3.14159;
n->next = NULL;
sp->name = "PHI";
sp->value = 1.61803;
sp->next = n;
sp->length = 2;
}
while (1) {
if (sp->name == NULL) {
sp->name = strdup(s);
sp->next = NULL;
return sp;
} else if (strcmp(sp->name, s) == 0) {
return sp;
} else if (sp->next != NULL) {
sp = sp->next;
} else {
struct sym *n = (struct sym *)malloc(sizeof(struct sym));
n->name = strdup(s);
sp = original;
struct sym *old = NULL;
while (1) {
if (strcmp(sp->name, s) > 0) {
// new variable name comes before in ascii table
if (old == NULL) {
// new node insert at beginning of sym_p
n->next = original;
n->length = original->length;
sym_p = n;
original = sym_p;
sp = original;
} else {
// insert in middle and update links
old->next = n;
n->next = sp;
sp = original;
}
break;
} else {
if (sp->next != NULL) {
old = sp;
sp = sp->next;
} else {
sp->next = n;
break;
}
}
}
sp = original;
sp->length++;
return n;
}
}
}
void sym_inventory()
{
struct sym * sp = sym_p;
printf("num-syms: %d\n", sp->length);
int i;
int length = sp->length;
for (i = 0; i < length; i++) {
printf("\t%s => %g\n", sp->name, sp->value);
sp = sp->next;
}
}
问题
您的语法无法将空行识别为有效输入。当您键入 ?
后跟一个换行符时,将返回换行符,这在语法上是无效的,因此会出现 'syntax error' 报告。
例如,您可以通过键入 ?a + b
作为输入进行演示。
请注意,您的词法分析器在处理 ?
时并没有让解析器知道它发生了;解析器永远不会看到 ?
.
敦促获得足够的信息来回答问题
Lex 代码的这种改编表明词法分析器将 ?
识别为输入。您的问题没有显示代码的使用方式,因此没有足够的信息让我们知道您做错了什么。您需要提供一个MCVE(Minimal, Complete, Verifiable Example),以便获得相关帮助。
%option noinput
%option nounput
%%
"?" { printf("Got a ?\n"); }
([0-9]+|([0-9]*\.[0-9]+)([eE][+-]?[0-9]+)?) {
printf("Number: %s\n", yytext);
}
[ \t] { printf("Space: [%s]\n", yytext); }
[A-Za-z][A-Za-z0-9]* {
printf("Name: %s\n", yytext);
}
"$" { printf("Dollar\n"); return 0; }
\n |
. { printf("Other: %c\n", yytext[0]); return yytext[0]; };
%%
int yywrap(void) { return 1; }
int main(void)
{
while (yylex() != 0)
;
return 0;
}
示例 运行(shell 提示是 JL:
而不是 $
因为输入之一是 $
):
JL: ./xy73
a b 23
Name: a
Space: [ ]
Name: b
Space: [ ]
Number: 23
Other:
?
Got a ?
Other:
=@%
Other: =
Other: @
Other: %
Other:
$
Dollar
JL:
那个?后跟一个作为字符标记返回的换行符,但您的语法只接受语句后的换行符,该语句始终以 NAME 开头。