ПО, ЭВМ и АСУ из Таможенного Союза

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » ПО, ЭВМ и АСУ из Таможенного Союза » регулярные выражения » Про выкидывание пробелов


Про выкидывание пробелов

Сообщений 1 страница 3 из 3

1

Многие лексеры стремятся выкинуть пробелы (в том числе концы строк) и при этом не сохраняют/не предоставляют информацию о номерах строк.
Это затрудняет создание операций для текстового редактора и создание диффов при модификации.

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

0

2

про отслеживание номеров строк.

http://stackoverflow.com/questions/6567 … on-exactly
https://www.gnu.org/software/bison/manu … -Locations

Though grammar rules and semantic actions are enough to write a fully functional parser,
it can be useful to process some additional information, especially symbol locations.

One way to do that is to add yycolumn = 1 rules everywhere a newline shows up
but if you don want to keep track of all the places a newline could show up (whitespace, comments, etc...)
an alternative is inspecting the yytext buffer at the start of every action

We can do this in the YY_USER_ACTION macro, which is called just before any lexer action is performed; that ensures that if a rule matches but it doesn't return a value (for instance, a rule skipping whitespace or comments), the location of that non-token is skipped, rather than being included at the beginning of the actual token, or lost in a way that makes the location tracking inaccurate.

The YYLLOC_DEFAULT macro is invoked each time a rule is matched, before the associated action is run. It is also invoked while processing a syntax error, to compute the error’s location. Before reporting an unresolvable syntactic ambiguity, a GLR parser invokes YYLLOC_DEFAULT recursively to compute the location of that ambiguity.

Combined with what you found in the Flex manual, that may be sufficient.

Neither bison nor flex updates yylloc automatically, but it's actually not difficult to do it yourself—if you know the trick.
The trick to implementing yylloc support is that, even though yyparse() declares yylloc, it never changes it.

The way locations are handled is defined by providing a data type, and actions to take when rules are matched.

When YYLTYPE is not defined, Bison uses a default structure type with four members:

typedef struct YYLTYPE
{
  int first_line;
  int first_column;
  int last_line;
  int last_column;
} YYLTYPE;

In your parser add:

%locations

Adding --locations to the command line OR %locations after the grammar will mean that yylloc is in scope of the .y file,
provided you refer to it from code in the final "%%" section.

at the beginning of the parsing, Bison initializes all these fields to 1 for yylloc.

in your lexer:

%option yylineno

once you start keeping track of column numbers by hand
you might as well also keep track of the line numbers in the same place and not bother with using Flex's yylineno option.

what you need to do is keep track of the newlines yourself instead of relying on %option yylineno

%{

#define YY_USER_ACTION \
    yylloc->first_line = yylloc->last_line; \
    yylloc->first_column = yylloc->last_column; \
    for(int i = 0; yytext[i] != '\0'; i++) { \
        if(yytext[i] == '\n') { \
            yylloc->last_line++; \
            yylloc->last_column = 0; \
        } \
        else { \
            yylloc->last_column++; \
        } \
    }

%}

or

static void update_loc(YYLTYPE *loc, char *txt) { loc->first_line = ...}
#define YY_USER_ACTION update_loc(yylloc, yytext);

Flex has the useful macro YY_INPUT, which reads data for token interpretation. You can add a call in YY_INPUT to the function GetNextChar(), which reads the data from a file and keeps information about the position of the next character to read. GetNextChar() uses a buffer to hold one line of input. Two variables store the current line number and the next position in the line:

#define YY_INPUT(buf,result,max_size)  {\
    result = GetNextChar(buf, max_size); \
    if (  result <= 0  ) \
      result = YY_NULL; \
    }

lexical analyzer will track line number and column number information for each token
and make them available within parser actions.

http://bajiecc.cc/questions/2409965/pro … -bison-3-0

If you're using %define api.pure in bison to create a reentrant parser, you also need to specify %option bison-locations in flex. This is because in a reentrant parser yylloc is not a global variable, and needs to be passed into the lexer.

So, in the parser:

%define api.pure
%locations

in the lexer:

#include "yourprser.tab.h"
#define YY_USER_ACTION yylloc.first_line = yylloc.last_line = yylineno;
%option bison-locations
%option yylineno

The API of Bison:
https://www.gnu.org/software/bison/manu … -Locations

In addition, the named references construct @name and @[name] may also be used to address the symbol locations

@$.first_column = @1.first_column;
@$.first_line = @1.first_line;
@$.last_column = @3.last_column;
@$.last_line = @3.last_line;

there is a default action for locations that is run each time a rule is matched.
It sets the beginning of @$ to the beginning of the first symbol, and the end of @$ to the end of the last symbol.
With this default action, the location tracking can be fully automatic.

It is also possible to access the location of the lookahead token, if any, from a semantic action.
This location is stored in yylloc.

@n
Acts like a structure variable containing information on the textual location of the nth component of the current rule.

@$
Acts like a structure variable containing information on the textual location of the grouping made by the current rule.

$$
Acts like a variable that contains the semantic value for the grouping made by the current rule.

$n
Acts like a variable that contains the semantic value for the nth component of the current rule.

$<typealt>$
Like $$ but specifies alternative typealt in the union specified by the %union declaration.

$<typealt>n
Like $n but specifies alternative typealt in the union specified by the %union declaration.

Variable: yylloc
Variable containing the lookahead token location when yychar is not set to YYEMPTY or YYEOF.
Do not modify yylloc in a deferred semantic action

Variable: yylval
Variable containing the lookahead token semantic value when yychar is not set to YYEMPTY or YYEOF.
Do not modify yylval in a deferred semantic action

http://oreilly.com/linux/excerpts/97805 … overy.html

Отредактировано Лис (2017-04-15 07:46:48)

0

3

Вобщем, они всё делают неправильно. Они акцентируются на помежутках между элементами контента. А нужно акцентироваться на самих элементах контента.

Опишем контент (второй) упрощенной грамматикой (например в книге можно сослаться: страница->абзац->предложение->слово->буква. Или на форуме можно указать: категория -> форум -> тема -> номер собщения -> строка -> номер слова). Можно сослаться на любой логический элемент текста. Можно преобразовать индекс в файле в локатор буквы по грамматике. (Седьмая буква второго слова третьего предложения первого абзаца на двадцатьшестой странице).

Упрощенная грамматика вероятно будет иметь общие определения с основной грамматикой (что буквой является, что цифрой и т.п.)

Идея в том, что операции текстового редактора формулируются в терминах этой вспомогательной грамматики (добавить абзац, удалить абзац и т.п.)
Имея две связанные грамматики можно будет сказать, что поменялось при таком-то действии в текстовом редакторе.

Все фрагменты текста начинаются с какой-то позиции в файле и имеют какую-то длину. Их N*(N-1)/2 штук.
Можно хранить не все, а только те, которые соответствуют правилам одной из грамматик. Глядя на отрезки можно определить что с чем пересекается или полностью включено одно в другое.

Таким образом, описание позиции в тексте - это не работа лексера, это работа синтаксического анализатора (парсера).

Хотя если в структуре не может быть произвольного количества уровней вложенности, то хватит и ДКА (например если текст состоит просто из строк)...

Отредактировано Лис (2017-04-15 09:27:28)

0


Вы здесь » ПО, ЭВМ и АСУ из Таможенного Союза » регулярные выражения » Про выкидывание пробелов