Форум программистов, компьютерный форум CyberForum.ru

Интерпретатор - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 14, средняя оценка - 4.93
nobless1368
 Аватар для nobless1368
14 / 14 / 1
Регистрация: 04.06.2012
Сообщений: 124
Записей в блоге: 1
21.01.2013, 11:42     Интерпретатор #1
Почитал книгу по написанию компиляторов и интерпретаторов Dragon Book. На 90+ страницах есть листинг простого интерпретатора, который я третий день не могу собрать. Основная проблема в файле init.c. Прошу помочь разобраться, как исправить листинг.

global.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#pragma once
#ifndef GLOBAL_H
#define GLOBAL_H
 
#endif // GLOBAL_H
 
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <iostream>
 
#define BSIZE 128
#define NONE -1
#define EOS '\0'
 
#define NUM 256
#define DIV 257
#define MOD 258
#define ID 259
#define DONE 260
 
using std::cout;
using std::endl;
 
extern int tokenval;
extern int leneno;
 
struct entry {
    char *lexptr;
    int token;
};
 
extern struct entry symtable[];
 
int parse();    //parser.cpp
int expr();
int term();
int factor();
int match(int t);
 
int lookup(char s[]);   //symbol.cpp
int insert(char s[], int tok);
 
void emit(int t, int tval); //emitter.cpp
 
int init(); //init.cpp
main.cpp
C++
1
2
3
4
5
6
7
8
9
#include "global.h"
 
int main()
{
    init();
    parse();
//    exit();
    return 0;
}
init.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "global.h"
 
struct centry keywords[]=
{
    "div", DIV,
    "mod", MOD,
    0, 0
};
 
int init()
{
    struct centry *p = keywords;
    for(; p->token; p++)        //добавить условие
        insert(p->lexptr, p->token);
    return 0;
}
emitter.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include "global.h"
 
void emit(int t, int tval)
{
    switch (t) {
    case '+': case '-': case '*': case '/':
        printf ("%c\n", t) ; break;
    case DIV:
        printf ("DIV\n") ; break;
    case MOD:
        printf ("MOD\n") ; break;
    case NUM:
        printf ("%d\n", tval); break;
    case ID:
        printf ( "%s\n", symtable [tval].lexptr) ; break;
    default :
        printf ("token %d, tokenval %d\n", t, tval);
    }
}
lexer.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include "global.h"
 
char lexbuf[BSIZE];
int lineno = 1;
int tokenval = NONE;
 
int lexan()
{
    int t;
    while (1) {
        t = getchar ();
        if (t == ' ' || t == '\t');
        else if (t == '\n')
            lineno++;
        else if (isdigit(t)) { /* t - цифра */
            ungetc(t, stdin);
            scanf("%d", &tokenval);
            return NUM;
        }
        else if (isalpha(t)) {
            int p, b = 0;
            while (isalnum(t)) {
                lexbuf[b++] = t;
                t = getchar();
                if (b >= BSIZE)
                    cout << "compiler error" << endl;
            }
            lexbuf[b] = EOS;
            if (t != EOF)
                ungetc(t, stdin);
            p = lookup(lexbuf);
            if (p == 0)
                p = insert(lexbuf, ID);
            tokenval = p;
            return symtable[p].token;
        }
        else if (t == EOF)
            return DONE;
        else {
            tokenval = NONE;
            return t;
        }
    }
    return 0;
}
parser.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include "global.h"
#include "lexer.cpp"
 
int lookahead;
 
int parse()
{
    lookahead = lexan();
    while (lookahead != DONE) {
        expr();
        match(';');
    }
    return 0;
}
 
int expr()
{
    int t;
    term();
    while(1)
    switch(lookahead){
        case '+' : case '-' :
            t = lookahead;
            match(lookahead) ;
            term();
            emit(t, NONE);
            continue;
        default :
            return 0;
    }
    return 0;
}
 
int term()
{
    int t;
    factor ();
    while (1)
    switch (lookahead) {
        case (' * ' || '/' || DIV || MOD):
            t = lookahead;
            match (lookahead) ;
            factor();
            emit(t, NONE);
            continue;
        default :
            return 0;
    }
    return 0;
}
 
int factor()
{
    switch (lookahead) {
    case '(' :
        match ('(');
        expr();
        match(')');
        break;
    case NUM:
        emit (NUM, tokenval);
        match (NUM);
        break;
    case ID:
        emit (ID, tokenval);
        match (ID);
        break;
    default:
        cout << "syntax error" << endl;
    }
    return 0;
}
 
int match(int t)
{
    if (lookahead == t)
        lookahead = lexan();
    else cout << "syntax error" << endl;
    return 0;
}
symbol.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include "global.h"
 
#define STRMAX 999
#define SYMMAX 100
 
char lexemes [STRMAX] ;
int lastchar = -1;
 
struct entry symtable [SYMMAX] ;
int lastentry = 0;
 
int lookup(char s[])
{
    int p;
    for(p = lastentry; p > 0; p --)
        if (strcmp(symtable [p].lexptr, s) == 0)
            return p;
    return 0;
}
 
int insert(char s[], int tok)
{
    int len;
    len = strlen(s);
    if (lastentry + 1 >= SYMMAX)
        cout << "symbol table full" << endl;
    if (lastchar + len + 1 >= STRMAX)
        cout << "lexemes array full" << endl;
    lastentry++;
    symtable[lastentry].token = tok;
    symtable[lastentry].lexptr = &lexemes[lastchar + 1];
    lastchar += len + 1;
    strcpy(symtable[lastentry].lexptr, s);
    return lastentry;
}
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
21.01.2013, 11:42     Интерпретатор
Посмотрите здесь:

C++ Интерпретатор(asm)
интерпретатор cmd C++
C++ Реализовать командный интерпретатор
C++ Интерпретатор с++ с открытым кодом
командный интерпретатор C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
nobless1368
 Аватар для nobless1368
14 / 14 / 1
Регистрация: 04.06.2012
Сообщений: 124
Записей в блоге: 1
22.01.2013, 22:40  [ТС]     Интерпретатор #2
По прежнему актуально.
Issues
429 / 364 / 37
Регистрация: 06.08.2012
Сообщений: 961
22.01.2013, 22:44     Интерпретатор #3
я конечно не уверен, но разве так можно?
Цитата Сообщение от nobless1368 Посмотреть сообщение
struct centry keywords[]=
nobless1368
 Аватар для nobless1368
14 / 14 / 1
Регистрация: 04.06.2012
Сообщений: 124
Записей в блоге: 1
22.01.2013, 23:03  [ТС]     Интерпретатор #4
нет, нельзя, но я не знаю как это исправить, чтобы не переписывать весь интерпретатор.

Поясню что должно происходить в init.cpp:
Создается алфавит из лексем языка для распознавания их в интерпретируемом тексте.
villu
202 / 202 / 4
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
22.01.2013, 23:12     Интерпретатор #5
ошибки то где?
BTW:
C++
1
2
3
4
struct entry {
    char *lexptr;
    int token;
};
А тут кто такой centry?
C++
1
struct centry keywords...
krdev
2 / 2 / 0
Регистрация: 19.02.2012
Сообщений: 12
22.01.2013, 23:15     Интерпретатор #6
мож я чего то не понимаю, но не нашел определения struct centry, в отличие от struct entry.
nobless1368
 Аватар для nobless1368
14 / 14 / 1
Регистрация: 04.06.2012
Сообщений: 124
Записей в блоге: 1
22.01.2013, 23:16  [ТС]     Интерпретатор #7
По мне так весь init.cpp одна сплошная ошибка. keywords должен быть массивом для хранения алфавита интерпретатора, но я понятия не имею как в один массив можно засунуть и целочисленные константы и строковые...
villu
202 / 202 / 4
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
22.01.2013, 23:20     Интерпретатор #8
Цитата Сообщение от nobless1368 Посмотреть сообщение
но я понятия не имею как в один массив можно засунуть и целочисленные константы и строковые
структура же описана. Подозреваю, правда, что ошибка в имени в init.cpp.
nobless1368
 Аватар для nobless1368
14 / 14 / 1
Регистрация: 04.06.2012
Сообщений: 124
Записей в блоге: 1
22.01.2013, 23:31  [ТС]     Интерпретатор #9
Огромное спасибо всем откликнувшимся!

Итого:
1. Ошибка в именовании структуры entry в init.cpp
2. В parser.cpp не нужно иклюдить никаких lexer.cpp, а лучше функцию lexan() занести в хедер.
3. Есть подозрение, что в init() не правильно записан цикл for, но это я сам дотащу как-нибудь.
villu
202 / 202 / 4
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
22.01.2013, 23:39     Интерпретатор #10
Цитата Сообщение от nobless1368 Посмотреть сообщение
Есть подозрение, что в init() не правильно записан цикл for,
правильно написан
C++
1
for(; p->token; p++)
тоже самое
C++
1
for( p=keywords; p->token!=NULL; p++)
nobless1368
 Аватар для nobless1368
14 / 14 / 1
Регистрация: 04.06.2012
Сообщений: 124
Записей в блоге: 1
22.01.2013, 23:46  [ТС]     Интерпретатор #11
Тем не менее почему-то он отказывается выводить последний символ...

Вход: 9-5+2
Выход: 95-2
Должно быть: 95-2+

Если есть идеи - милости прошу. Сам сейчас сижу ковыряю
villu
202 / 202 / 4
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
22.01.2013, 23:54     Интерпретатор #12
а какой код выводит эту строку?

или вот, например, что я вижу тут:
C++
1
2
3
4
5
6
7
8
int lookup(char s[])
{
    int p;
    for(p = lastentry; p > 0; p --)
        if (strcmp(symtable [p].lexptr, s) == 0)
            return p;
    return 0;
}
идет поиск снизу вверх, но упускается один элемент массива, так как индексы начинаются с 0 (как у тебя и инициализируется; lastentry = 0). То есть нужно:
C++
1
for(p = lastentry; p >= 0; p --)
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
23.01.2013, 17:29     Интерпретатор
Еще ссылки по теме:

C++ Простенький интерпретатор
Маленький (команд на 10) интерпретатор на C++ C++
C++ Написать интерпретатор

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
nobless1368
 Аватар для nobless1368
14 / 14 / 1
Регистрация: 04.06.2012
Сообщений: 124
Записей в блоге: 1
23.01.2013, 17:29  [ТС]     Интерпретатор #13
Сам вывод в emitter.cpp

Но я сейчас выяснил, что интерпретатор не распознает еще и некоторые лексемы, которые заданы в списке keywords, а конкретно DIV и MOD. Значит, ошибка, скорее всего, есть в symbol.cpp, который отвечает за анализ входных символов.

Добавлено через 17 часов 19 минут
По прежнему актуально.
Yandex
Объявления
23.01.2013, 17:29     Интерпретатор
Ответ Создать тему
Опции темы

Текущее время: 09:25. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru