Атрибуты токена - PullRequest
       8

Атрибуты токена

0 голосов
/ 14 января 2011

Я написал простой лексический анализатор.И я понимаю необходимость предоставления каждому распознанному токену атрибута.Давайте посмотрим, что я получил:

public sealed class Token
{ 
    public enum TokenClass
    { 
        Identifier,
        StringLiteral,
        NumberLiteral,
        Operator,
        PunctuationSeparator,
        Bracket,
        Parenthesis
    }        
    public TokenClass Class { get; internal set; }
    public String     Value { get; internal set; }
}

В лексере я ставлю токены в очередь, устанавливая их значение и класс.Но как насчет атрибутов?Как мне разработать функцию относительно моего существующего класса токенов?

Первое, что пришло мне в голову, было:

  1. Объявить частные абстрактные классы "неоднозначных сущностей" (я имею в виду, чтоЧисло может быть целым и действительным и т. Д.) Внутри класса токена;
  2. Затем объявить унаследованные классы, например public class Comma : PunctuationSeparator {};
  3. Добавить свойство Object Attribute {get; private set;};
  4. Затем создать методкак private void ApplyAttribute();
  5. Вызов ApplyAttribute(), когда создается токен и установлены свойства;
  6. Используйте что-то подобное внутри ApplyAttribute().

    switch(this.TokenClass)
    {
    case this.TokenClass.Number:
        {
            this.Attribute = (Int32.TryParse(this.Value))? new Integer() : new Real();                
        }
    }
    

В парсере было бы легко написать что-то подобное if(CurToken.Attribute is Integer).Одна вещь, которая мешает мне делать это, это количество классов, которые я должен создать.Это решение приемлемо?

Ответы [ 2 ]

2 голосов
/ 14 января 2011

Атрибуты, которые я бы использовал для токена? Возможно, что-то вроде

public class Token
{
  public TokenType Type { get ; private set ; }
  public string    Text { get ; private set ; }
  public int       LineNumber { get ; private set ; }
  public int       Column     { get ; private set ; }
}

public enum TokenType
{
  Keyword : 1 ,
  Integer ,
  String  ,
  Whitespace ,
  Comment ,
  ... 
}

Однако я не согласен с предыдущим постером относительно преобразования текста токена в «значение». ИМХО, это домен парсера и узлы дерева разбора. Пока синтаксический анализатор не поместит токены в контекст WRT грамматики, токен - это просто фрагмент текста с прикрепленной к нему меткой. Лексический анализатор не знает (и должен заботиться) о том, что происходит в нисходящем направлении - все, что он знает, это просто печатать исходный текст (в этом случае вы хотите оставить отдельные токены в покое).

Возможно, вы захотите взглянуть на книгу (книги) Терранса Парра:

0 голосов
/ 14 января 2011

вместо

public String Value { get; internal set; }

просто используйте

public object Value { get; internal set; }

и затем сохраните целочисленные значения или значения с плавающей запятой там как целое число или значение с плавающей запятой. Тогда в вашем парсере вы можете просто сказать

if (token.Value == null)
{
    // blah
}
else if (token.Value is int)
{
    // work with (int) token.Value
}
else if (token.Value is double)
{
    // work with (double) token.Value
}
else if (token.Value is string)
{
    // work with (string) token.Value
}

или альтернативно:

int? integer;
double? floating;
string str;

if (token.Value == null)
{
    // blah
}
else if ((integer = token.Value as int?) != null)
{
    // work with integer.Value
}
else if ((floating = token.Value as double?) != null)
{
    // work with floating.Value
}
else if ((str = token.Value as string) != null)
{
    // work with str
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...