2010-11-25 6 views
1

Gibt es eine Möglichkeit, um 2 oder mehr Operanden in einem YACC Projekt unter Verwendung der Programmiersprache C hinzufügen, um einen Parser für ein LISP-Subset zu erstellen, ist dies die GrammatikOperationen mit YACC in C für eine LISP Teilmenge

„mod "und‚lassen‘muss nicht beachtet werden, weder die Symbole

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 
    ; 

ich loooking bin zu wissen, wie eine Symboltabelle zu verwenden und eine Addition, Subtraktion, Multiplikation, Division und mod, eine Liste von Elementen und Variablen deklarieren Ich habe keine Ahnung, wie man eine Symboltabelle im Code benutzt.

zum Beispiel sind diese Sätze gelten für die Sprache:

(+ 30 -7 +3) 

Ergebnis ist 26

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

Ergebnis -49

(lEt ((x(+ 1 2))(y x))(/ (mod x y) 3)) 

Ergebnis 0

Jede Hilfe ist willkommen Kommen Sie. Vielen Dank im Voraus.

Antwort

1

Hmm, ich sehe mehrere Probleme.

Zum einen, ich nehme an, die Nicht-Terminal CUERPO sollte eigentlich als BODY eingegeben worden sein, richtig?

Zweitens wird diese Grammatik tatsächlich keinen dieser Testfälle analysieren.

Alle Testfälle erfordern einen Operator und dann mehrere Ausdrücke mit zusätzlichen Operatoren, aber die einzige Regel, die einem Operator erlaubt, erfordert auch neue Parens.

Nun, Ihre Grammatik wird Parse:

(+1 2 3 a b fnorq bletch) 

und ähnliche Sätze ...

ich eine Symboltabelle vor dem Hinzufügen und Ausführen tatsächlich die Arithmetik, die Grammatik und das Parsen richtig bekommen würde vorschlagen . Mit einem funktionierenden Framework wird die Anforderung, die tatsächlichen Werte von Symbolen zu finden, die Theorie, den Betrieb und die Entwicklung einer Symboltabelle viel offensichtlicher machen.

Ich habe Ihre Grammatik in ein tatsächliches „Arbeit“ Programm gemacht:

$ 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