【问题标题】:Operations with YACC in C for a LISP subset在 C 中对 LISP 子集使用 YACC 的操作
【发布时间】:2010-11-25 21:22:01
【问题描述】:

有什么方法可以在 YACC 项目中添加 2 个或多个操作数,使用 C 语言为 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

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

【问题讨论】:

    标签: c lisp yacc lex


    【解决方案1】:

    嗯,我发现有几个问题。

    首先,我想非终端 CUERPO 实际上应该输入为 BODY,对吧?

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

    所有测试用例都需要一个运算符,然后是多个带有附加运算符的表达式,但允许运算符的唯一规则还需要新的括号。

    现在,您的语法解析:

    (+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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-25
      • 1970-01-01
      • 2013-04-15
      • 1970-01-01
      • 2010-09-07
      • 2016-03-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多