2010-11-25 23 views
1

Est-il possible d'ajouter 2 opérandes ou plus dans un projet YACC en utilisant le langage C pour créer un analyseur syntaxique pour un sous-ensemble LISP, c'est la grammaireOpérations avec YACC en C pour un sous-ensemble LISP

« mod »et « laisser » ne sont pas sensibles à la casse, ni les symboles

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 
    ; 

Je loooking de savoir comment utiliser une table de symboles et d'ajouter, soustraire, multiplier, diviser et mod, une liste d'éléments, et déclarer des variables Je n'ai aucune idée de comment utiliser une table de symboles dans le code.

par exemple, ces phrases sont valables pour la langue:

(+ 30 -7 +3) 
résultat

est 26

(* (+ 3 4) (- -5 2)) 

résultat est -49

(lEt ((x(+ 1 2))(y x))(/ (mod x y) 3)) 
résultat est

Toute aide est la bienvenue viens. Merci d'avance.

Répondre

1

Hmm, je vois plusieurs problèmes.

Pour un, je suppose que le CUERPO non-terminal aurait dû être tapé BODY, n'est-ce pas? Deuxièmement, cette grammaire n'analyse en fait aucun de ces cas de test. Tous les cas de test nécessitent un opérateur, puis plusieurs expressions avec des opérateurs supplémentaires, mais la seule règle qui autorise un opérateur nécessite également de nouvelles parens.

Maintenant, votre grammaire va Parse:

(+1 2 3 a b fnorq bletch) 

et expressions similaires ...

Je vous conseille de prendre la grammaire et l'analyse correcte avant d'ajouter une table de symboles et exécuter réellement l'arithmétique . Avec un cadre de travail, l'exigence de traquer les valeurs réelles des symboles rendra la théorie, le fonctionnement et le développement d'une table de symboles beaucoup plus évidents.

J'ai fait votre grammaire dans un programme « travail » réelle:

$ 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