2011-01-13 2 views
0

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

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. Объявить частные абстрактные классы «неоднозначных-сущностей» (я имею в виду, что номер может быть Integer и Real и т.д.) внутри маркера класса;
  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). Одна вещь, которая мешает мне делать это, - это количество классов, которые я должен создать. Является ли это решение приемлемым?

+0

У вас есть онтология домена? Не должно быть, чтобы вы делали всевозможные пустые классы. Вы уже создали структуру наследования? Возможно, установка различных типов «ПунктуацияSeperator's» достаточно. – Marnix

+0

Нет, я еще не создал ничего описанного здесь. Это только мои планы и сомнения. Кажется, это полезно, но ... классы ... я не могу решить .. помогите :) Что значит сказать последнее предложение? – lexeme

+1

При создании класса, такого как 'PunctuationSeperator'. Было бы также полезно определить перемычку там, с разными значениями [запятая, период, полуколокон]. Итак, сначала, я думаю, вы должны определить, как ваш домен, прежде чем принимать такое решение. – Marnix

ответ

2

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

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 , 
    ... 
} 

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

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

+0

Просмотрел книги! Большое спасибо! – lexeme

0

Вместо

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 
} 
+0

Это хорошо с примитивными типами, но как насчет скобок или фигурных скобок? как мне настроить значение? – lexeme

+0

@helicera: Во-первых, «объект» не ограничивается примитивными типами. Вы можете положить все, что захотите. Но во-вторых, какое «значение» вам нужно для токена скобок? Я ожидаю, что будет существовать токен типа OpenParenthesis и CloseParenthesis с нулевым значением. В качестве альтернативы, конечно, у вас может быть тип токена «PunctuationSymbol» и хранить '' («строка в' Value', но лично я бы нашел, что hacky. – Timwi