Разбор строки в D - PullRequest
       3

Разбор строки в D

2 голосов
/ 10 декабря 2011

Я пытаюсь выучить D, но борюсь с отсутствием документации (или моим пониманием этого), поэтому я пришел сюда. Сегодня я уже задавал другой, но не связанный с этим вопрос.

Во всяком случае, здесь идет:

Я бы хотел разобрать строку для разных вещей.

Формат строки примерно такой:

[<label>] <mnemonic> [parameters]

Если метки нет, есть обязательные пробелы. Параметры могут быть разделены запятыми. Типы параметров зависят от мнемоники.

Я хотел бы использовать std.conv: parse из библиотеки Фобоса, чтобы помочь мне, но я не понимаю документации о том, как анализировать «слово», как, например, некоторые символы, разделенные пробелами на обоих концах. Он отлично работает для целых чисел и тому подобное, как int i = parse!int(line). Но если бы я сделал string s = parse!string(line), он бы захватил всю строку.

Я анализирую это вручную, используя char** (или ref string) в качестве типа данных, точно так же, как я делал, когда писал это в C. Но я учусь D, чтобы не делать этого.

Я пытался сделать что-то подобное, чтобы сделать это вручную:

string get_word(ref string s)
{
        int i = 0;
        while (i < s.length && isAlphaNum(s[i]))
                i++;

        string word = s[0 .. i];
        s = s[i+1 .. $];
        return word;
}

Это хороший способ сделать это? Есть ли более чистый способ? Более быстрый способ? Возможно, более безопасный путь? Я не уверен, что индекс i+1 всегда существует.

Спасибо за помощь!

Моя вера в D уже немного истощается, так как я столкнулся с всевозможными проблемами. Но путь наверняка будет стоить того.

Ответы [ 2 ]

2 голосов
/ 12 декабря 2011

Прежде всего, std.conv.parse предназначен для преобразования вещей в строки, а не в синтаксическом анализе в смысле разделения и понимания строки. Насколько сложное решение вам нужно, будет зависеть от сложности грамматики вашей строки формата. Посмотрите на std.string.split, который по умолчанию разделит ваш ввод на пробелы и вернет массив слов. Если формат слишком сложный, вы можете:

  1. использовать регулярное выражение с захватами: http://d -programming-language.org / phobos / std_regex.html # RegexMatch

  2. написать свой собственный парсер, который продвигает символ за символом и извлекает необходимую информацию.

1 голос
/ 10 декабря 2011

код написан на лету

import std.string;
import std.stdio;
import std.algorithm;
import std.math;

enum string[] separators = [ " ", "\t", ",", ";", "\n", "\r\n" ];

string get_word( ref string s ){
    string token;
    sizediff_t storePositions[separators.length + 1]; // set size array to the number of separator in array "separators" and latest field for current string lenght 
    foreach( i, separator; separators ){             // compute position for each separator
        sizediff_t position = countUntil( s, separator );
        if( position == -1 ) position = sizediff_t.max;
        storePositions[i] = position;
    }
    storePositions[ $ -1 ] = s.length;
    sizediff_t end    = reduce!min( storePositions );
    token             = s[0 .. end].idup;
    writefln( "%s | %d", s, end );
    return token;
}

void main( string[] args ){
    string s        = "a long;string\tyeah\n strange; ok";
    bool   isRunning= true;
    size_t start    = 0;
    writefln( "parse: %s", s ); 
    while( isRunning ){
        string result = get_word( s[ start .. $] );
        if( result == "" )
            isRunning = false;
        else{
            start  += result.length + 1;
            result = get_word( s[ start .. $] );
        }
        writefln( "token: %s, position: %d", result, start );
        writeln( "----" );
    } 
}

выход:

parse: a long;string yeah
 strange; ok
a long;string yeah
 strange; ok | 1
long;string yeah
 strange; ok | 4
token: long, position: 2
----
long;string yeah
 strange; ok | 4
string yeah
 strange; ok | 6
token: string, position: 7
----
string yeah
 strange; ok | 6
yeah
 strange; ok | 4
token: yeah, position: 14
----
yeah
 strange; ok | 4
 strange; ok | 0
token: , position: 19
----
 strange; ok | 0
token: , position: 19

...