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

Пишем свой интерпретатор языка BASIC - C++

Войти
Регистрация
Восстановить пароль
Другие темы раздела
C++ Меню и список http://www.cyberforum.ru/cpp-beginners/thread41194.html
Здравствуйте форумчане. Помоги пожалуйста в следующем вопросе: У меня есть 2связный список, написано меню. Но в моменте когда написано make a list и delete custom необходимо чтобы выводились:...
C++ Здравствуйте! Не могу поместить class в один файл с программой. file.hpp #include "Cat.hpp" // здесь классы "2)" Cat::Cat(int initialAge) { itsAge = initialAge; } Cat::~Cat() { http://www.cyberforum.ru/cpp-beginners/thread41186.html
Массивы строк C++
Привет всем! Задан массив строк. Как узнать который символ встечаетса найбольшое количество раз в етом массиве?
C++ вывод на экран набор треугольников и квадратов, которые произвольно двигаются и меняют размер
Please, help me!!! Вот текст программы, которая выводит на экран набор треугольников и квадратов, которые произвольно двигаются и меняют размер только квадратов. Проблема в том, что необходимо...
C++ Округление дробного числа до целого в большую сторону. http://www.cyberforum.ru/cpp-beginners/thread41139.html
Доброго дня. Я новичок в программирование на Visual C++. Проблема такая программа должна считать кол-во месяцев, если числа целые то программа шла дальше, если дробное то (например 3.33333) ...
C++ Код из Delphi в C++ Нужно написать курсовую на C++. Сам я в программировании плохо шарю (не программист). Попросил у народу помощи, помогли. Но решение на Delphi: {$APPTYPE CONSOLE} type byteset=set of byte; ... подробнее

Показать сообщение отдельно
Evg
Эксперт CАвтор FAQ
18026 / 6258 / 427
Регистрация: 30.03.2009
Сообщений: 17,184
Записей в блоге: 27
13.07.2009, 09:36
Цитата Сообщение от #pragma Посмотреть сообщение
Хм,я объясню,почему выбрал этот вариант. Сначала я делал именно с Value как членом класса,но потом выяснилось,что необходим вызов конструктора Value,то есть требовалась запись вроде такой
C++
1
Variable a(paser_CurTokenStr,CONST_INT)
Чтобы сделать возможной вызов конструктора Value,причём получается что нужно,чтобы в paser_CurTokenStr было не имя переменной,а строка для константы. Я не нашёл другого способа,кроме как перегрузить оператор = для Variable. А как тебе видится решение?
А в каких случаях тебе нужно создавать переменную со значением? Просто для конструкции "LET a=5" получается что-то типа того:

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/* Ожидаем конструкцию вида Ident "=" Expr */
void
syntax_StmtLET (void)
{
  Variable *var;
  Value val;
 
  /* Читаем имя переменной (девая часть присваивания) */
  var = syntax_Ident(); // <--- здесь реализовано синтаксическое правило Ident
 
  /* Знак "=" */
  if (parser_GetToken() != TOKEN_DELIM_EQUAL)
    error ("syntax error near %s", parser_CurTokenStr);
 
  /* Значение выражения (правая часть присваивания) */
  val = syntax_Expr(); // <--- здесь реализовано синтаксическое правило Expr
 
  /* Строим присваивание */
  var->SetValue(val);
}
Добавлено через 22 минуты 36 секунд
syntax_parser.c строки 49-50. Ты пишешь, что создаёшь переменную, но это не правильно. Ты в данный момент парсишь ПРАВУЮ часть присваивания, т.е. там, где нужно читать значения. Т.е. все переменные уже должны быть созданы, а ты в этот момент НЕ создаёшь новую переменую, а достаёшь в таблице уже СУЩЕСТВУЮЩУЮ переменную и берёшь от неё значение. Если переменная не существует, то тут выбираешь как действовать: либо выдавать ошибку, либо считать, что для несуществующеё переменной значение равно нулю. Я бы выбрал первый вариант.

Возможно мне следовало пояснить момент, который для тебя совсем неочевиден. Имя переменной (в нашем случае это синтаксическое правило Ident) может встретиться в присваивании в правой части или в левой. В этих двух случаях оно трактуется по разному. Устоявшиеся технические термины для этого lvalue (от слова left) и rvalue (от right).

Когда имя переменной стоИт в позиции rvalue, то это означает, что нам нужно прочитать ЗНАЧЕНИЕ этой переменной, а когда в позиции lvalue (т.е. фактически мы хотим записать в переменную), то говорят, что нужно АДРЕС переменной. Адрес не в буквальном смысле слова, а в абстрактном - т.е. это нечто, при помощи которого мы можем записать значение в переменную. Иногда rvalue и lvalue называют соотвественно VALUE POSITION и NAME POSITION, но это несколько неудобная терминология из-за слова NAME

Вот примеры того, как переменная "AAA" находится в разных позициях

PureBasic
1
2
3
4
5
6
7
b = 1 + AAA    <--- rvalue (значение)
b = COS (AAA)  <--- rvalue (значение), имеем значение среди параметров
         (а необязательно после знака присваивания
 
AAA = 1  <--- lvalue (адрес)
INPUT AAA  <--- lvalue (адрес), т.е. здесь знака присваивания нет, но семантика
         оператора INPUT такова, что в переменную нужно записывать
Поэтому технически над синтаксическим правилом Ident можно сделать две настройки

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
Variable*
syntax_Ident (void)
{
  // Разгребаем имя переменной. Создаём переменную и возвращаем
  // на неё указатель. У меня была идея избавиться от создания
  // переменных без константы, но такой вариант принесёт больше гемора,
  // чем пользы. Лучше в переменной иметь дополнительный признак,
  // инициализирована переменная или нет. Поэтому вданной процедуре
  // мы просто заводим неинициализированную переменную
}
 
// Разбор имени переменной в левой части присваивания. Именно эту
// процедуру надо подставить в мой вышестоящий код. Здесь нам нужен
// только АДРЕС переменной (в том понятии, котором я описал выше),
// а поэтому просто возвращаем ссылку на созданную переменную
Variable*
syntax_IdentLValue (void)
{
  return syntax_Ident();
}
 
// Разбор имени переменной в левой части присваивания. Здесь
// нам нужно вернуть значение переменной
Value
syntax_IdentRValue (void)
{
  Variable *var;
 
  var = syntax_Ident();
 
  if (var неинициализирована)
    error ("неинициализированная переменная %s", var->GetName());
 
  return var->GetValue();
}
Вот что-то типа того

============================================

Ещё момент по твоему коду: value_class.h строки 85 и 86.
Именно то место, где слодовало бы поставить ASSERT (внутренний контроль), что от целой переменной нельзя брать плавающее значение и наоборот. Хотя в теории эти методы вообще не должны использоваться за пределами модуля Value (потому как все операции перегружены, печать значения реализована в виде интерфейса, больше снаружи вроде бы как незачем)

Добавлено через 5 минут 59 секунд
Я понял, почему у тебя получалось создание переменной непосредственно со значением. Но нужно было бы это делать с Value (т.е. распарсили строковое имя переменной, вытащили правую часть в виде Value, создали переменную с Value). Но засада в том, что тут переменную надо НЕ создавать, а записывать в неё (т.е. если переменная уже создана, то новая переменная не нужна)
1
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru