Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C中对LISP子集使用YACC的操作_C_Lisp_Yacc_Lex - Fatal编程技术网

在C中对LISP子集使用YACC的操作

在C中对LISP子集使用YACC的操作,c,lisp,yacc,lex,C,Lisp,Yacc,Lex,在YACC项目中,是否有任何方法可以使用C语言添加2个或更多操作数来为LISP子集构建解析器,这就是语法 “mod”和“let”不区分大小写,符号也不区分大小写 P: '('LET '('DEF_VARS')' BODY')' |BODY ; DEF_VARS: DEF_VARS DEF |DEF ; DEF: '('SYMBOL OPN')' ; CUERPO: BODY EXPR |EXPR ; EXPR

在YACC项目中,是否有任何方法可以使用C语言添加2个或更多操作数来为LISP子集构建解析器,这就是语法

“mod”和“let”不区分大小写,符号也不区分大小写

P:
    '('LET '('DEF_VARS')' BODY')'
    |BODY
    ;
DEF_VARS:
    DEF_VARS DEF
    |DEF
    ;
DEF:
    '('SYMBOL OPN')'
    ;
CUERPO:
    BODY EXPR
    |EXPR
    ;
EXPR:
    '('OPER OPNS')'
    ;
OPER:
    '+' 
    |'-'    
    |'*'    
    |MOD    // %
    |'/'    
    ;
OPNS:
    OPNS OPN
    |OPN        
    ;
OPN:
    EXPR        
    |INT    // [-+]?[0-9]+  
    |SYMBOL //[a-zA-Z][a-zA-Z0-9_]*     //a variable
    ;
我想知道如何使用符号表,加、减、乘、除、模、元素列表和声明变量 我不知道如何在代码中使用符号表

例如,以下句子适用于该语言:

(+ 30 -7 +3)
结果是26

(* (+ 3 4) (- -5 2))
结果是-49

( lEt ((x(+ 1 2))(y x))(/ (mod x y) 3))
结果是0

欢迎任何帮助。
提前谢谢。

嗯,我看到几个问题

首先,我想非终端
CUERPO
应该作为
BODY
输入,对吗

其次,该语法实际上不会解析这些测试用例中的任何一个

所有的测试用例都需要一个操作符,然后是多个带有额外操作符的表达式,然而唯一允许操作符的规则也需要新的参数

现在,您的语法将解析:

和类似的短语

我建议在添加符号表和实际执行算术之前,先纠正语法和解析。有了工作框架,查找符号实际值的要求将使符号表的理论、操作和开发更加明显

我已经把你的语法变成了一个实际的“工作”程序:

$cat>lispg.y
%{
char*yylval;
int yylex(无效);
无效错误(字符常量*);
#定义YYSTYPE字符*
int-yydebug=1;
%}
%代币出租
%象征符号
%标记整数
%令牌模式
%令牌符号\u太长\u
%%
P:“(“LET”(“DEF_VARS”)“BODY”)”
|身体
;
定义变量:
DEF_VARS DEF
|DEF
;
定义:
“('SYMBOL OPN')”
;
正文:
体膨胀
|EXPR
;
表达式:
“(‘操作选项’)”
;
操作员:
'+' 
|'-'    
|'*'    
|MOD/%
|'/'    
;
选项:
OPN
|骨桥蛋白
;
OPN:
EXPR
|INT/[-+]?[0-9]+
|SYMBOL//[a-zA-Z][a-zA-Z0-9\]*///a变量
;
%%
#包括
#包括
#包括
intparsesym(intc)
{
char*p;
静态字符符号[100];
对于(p=sym;p如果('a'Hmm),我看到几个问题

首先,我想非终端
CUERPO
应该作为
BODY
输入,对吗

其次,该语法实际上不会解析这些测试用例中的任何一个

所有的测试用例都需要一个操作符,然后是多个带有额外操作符的表达式,然而唯一允许操作符的规则也需要新的参数

现在,您的语法将解析:

和类似的短语

我建议在添加符号表和实际执行算法之前,先纠正语法和语法分析。有了工作框架,查找符号实际值的要求将使符号表的理论、操作和开发更加明显

我已经把你的语法变成了一个实际的“工作”程序:

$cat>lispg.y
%{
char*yylval;
int yylex(无效);
无效错误(字符常量*);
#定义YYSTYPE字符*
int-yydebug=1;
%}
%代币出租
%象征符号
%标记整数
%令牌模式
%令牌符号\u太长\u
%%
P:“(“LET”(“DEF_VARS”)“BODY”)”
|身体
;
定义变量:
DEF_VARS DEF
|DEF
;
定义:
“('SYMBOL OPN')”
;
正文:
体膨胀
|EXPR
;
表达式:
“(‘操作选项’)”
;
操作员:
'+' 
|'-'    
|'*'    
|MOD/%
|'/'    
;
选项:
OPN
|骨桥蛋白
;
OPN:
EXPR
|INT/[-+]?[0-9]+
|SYMBOL//[a-zA-Z][a-zA-Z0-9\]*///a变量
;
%%
#包括
#包括
#包括
intparsesym(intc)
{
char*p;
静态字符符号[100];
对于(p=sym;p(+1 2 3 a b fnorq bletch)
$ cat > lispg.y

%{

  char *yylval;

  int yylex(void);
  void yyerror(char const *);
  #define YYSTYPE char *
  int yydebug = 1;

%}

%token LET
%token SYMBOL
%token INT
%token MOD
%token SYMBOL_TOO_LONG

%%

P:  '('LET '('DEF_VARS')' BODY')'
    |BODY
    ;

DEF_VARS:
    DEF_VARS DEF
    |DEF
    ;
DEF:
    '('SYMBOL OPN')'
    ;
BODY:
    BODY EXPR
    |EXPR
    ;
EXPR:
    '('OPER OPNS')'
    ;
OPER:
    '+' 
    |'-'    
    |'*'    
    |MOD    // %
    |'/'    
    ;
OPNS:
    OPNS OPN
    |OPN        
    ;
OPN:
    EXPR        
    |INT    // [-+]?[0-9]+  
    |SYMBOL //[a-zA-Z][a-zA-Z0-9_]*     //a variable
    ;

%%

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int parsesym(int c)
{
char *p;
static char sym[100];


  for(p = sym; p < sym + sizeof sym - 1; ) {
    *p++ = c;
    c = getchar();
    if ('a' <= c && c <= 'z')
      c -= 'a' - 'A';
    if ('A' <= c && c <= 'Z' || '0' <= c && c <= '9' || c == '_')
      continue;
    *p++ = '\0';
    ungetc(c, stdin);
    if (strcmp(sym,"LET") == 0)
      return LET;
    yylval = strdup(sym);
    return SYMBOL;
  }
  return SYMBOL_TOO_LONG;
}

int parseint(int c) {
  parsesym(c);
  return INT;
}

int yylex() {
  for(;;) {
    int c;
    switch(c = getchar()) {
      case EOF:
        return 0;
      case ' ':
      case '\n':
      case '\t':
        continue;
      case '(':
      case ')':
      case '+':
      case '-':
      case '*':
      case '/':
        return c;
      case '%':
        return MOD;
      default:
        if('0' <= c && c <= '9')
          return parseint(c);
        if('a' <= c && c <= 'z')
          c -= 'a' - 'A';
        if('A' <= c && c <= 'Z') {
          return parsesym(c);
        }
    }
  }
}
$ yacc  lispg.y && cc -Wall -Wextra -Wno-parentheses y.tab.c -ly
$ echo '(+1 2 3 a b fnorq bletch)' | ./a.out