我正在尝试从markdown语法到Latex进行对话,反之亦然。但是我遇到了一个迄今为止我无法解决的问题。可以说,我们有以下文字:
* item
* item
* _Italic_ item
* Item with __nested _italic_ text__
现在,我的lex程序会对文本执行此操作:
\begin{itemize}
\item{item}
\item{item}
\item{_Italic_ item}
\item{Item with __nested _italic_ text__}
\end{itemize}
而且,如果我再次在该输出上运行程序,我会得到:
\begin{itemize}
\item{item}
\item{item}
\item{\textit{Italic} item}
\item{Item with nested \textit{italic} text}}
\end{itemize}
这是预期的结果,但它应该在一次运行中完成。
我想知道是否可以指示Flex在输出上再次运行yylex()
。阅读文档后我发现了Reentrant C Scanners
和Multiple Input Buffers
的内容,但我不知道这是否能解决我的问题。
什么是最佳解决方案?可重入扫描程序,多个输入缓冲区,还是更简单的东西?
我还想过实现函数yywrap
告诉lex再次启动扫描程序,但没有运气:
int yywrap(){
if (first_run == 1){
first_run++;
yyin = fopen ("/tmp/out1", "rt");
yyout = fopen("salida", "wt");
if (yyin == NULL) {
printf ("El fichero no se puede abrir\n");
exit (-1);
}
if (yyout == NULL) {
printf ("El fichero no se puede abrir\n");
exit (-1);
}
yyrestart(yyin);
return 0;
} else {
return 1;
}
}
这是我的代码:
/*----- Sección de Declaraciones --------------*/
%option case-insensitive
%option debug
%option verbose
%{
#include<stdio.h>
#include<string.h>
int from_italic_text = 0; /* Para saber si venimos de una italic anidada en la bold*/
int from_bold_text = 0;
%}
/* Primitives */
word .+
scstrong "__"|"**"
scem "_"|"*"
list ^"* "|"- "
%x IN_MARKDOWN_LIST
%x BOLD_TEXT_NESTED_ITALIC ITALIC_TEXT
%x BOLD_TEXT ITALIC_TEXT_NESTED_BOLD
%%
/*----- Sección de Reglas ----------------*/
{list} {BEGIN(IN_MARKDOWN_LIST);fprintf(yyout, "\\begin{itemize}\n");}
<IN_MARKDOWN_LIST>{
^\n fprintf(yyout, "\\end{itemize}\n\n");BEGIN(INITIAL); /* si volvemos a detectar línea vacia, hemos acabado el itemize, o no era nada y salimos */
^"* "|"- " /* Eliminar la sintáxis de itemize en markdown */
[^"*"\-\n]+ fprintf(yyout, "\t\\item{%s}\n", yytext); /* Éste es el texto que compone cada línea del itemize */
\n yylineno++;BEGIN(IN_MARKDOWN_LIST); /* Si detectamos salto de línea, aumentar el número de línea, y seguimos comprobando dentro de IN_MARKDOWN_LIST buscando más items*/
}
{scstrong} { BEGIN(BOLD_TEXT_NESTED_ITALIC); /* Comienzo de un strong __....*/}
<BOLD_TEXT_NESTED_ITALIC>{
"__" fprintf(yyout, "}");BEGIN(INITIAL); // Eat the end and exit
"_" BEGIN(ITALIC_TEXT); // Hay otro elemento anidado, un italic, pasamos a procesarlo
[^_\n]* {
if (from_italic_text)
fprintf(yyout, "%s", yytext); // Texto a continuación del italic
else
fprintf(yyout, "\\textbf{%s", yytext);
}
\n BEGIN(INITIAL);
}
<ITALIC_TEXT>{
[^_\n]* fprintf(yyout, "\\textit{%s", yytext);
"_" fprintf(yyout, "}"); BEGIN(BOLD_TEXT_NESTED_ITALIC); from_italic_text = 1; /* Llegado al último _, cerramos }, volvemos al stado BOLD_TEXT y ponemos from_italic_text a 1 para saber que estuvimos aquí, y no cerra antes de tiempo el \textbf*/
}
{scem} { BEGIN(ITALIC_TEXT_NESTED_BOLD); /* Comienzo de un strong __....*/}
<ITALIC_TEXT_NESTED_BOLD>{
"_" fprintf(yyout, "}"); BEGIN(INITIAL); // Eat the end and exit
"__" BEGIN(BOLD_TEXT); // Hay otro elemento anidado, un italic, pasamos a procesarlo
[^_\n]* {
if (from_bold_text)
fprintf(yyout, "%s", yytext); // Texto a continuación del italic
else
fprintf(yyout, "\\textit{%s", yytext);
}
\n BEGIN(INITIAL);
}
<BOLD_TEXT>{
[^_\n]* fprintf(yyout, "\\textbf{%s", yytext);
"__" fprintf(yyout, "}"); BEGIN(ITALIC_TEXT_NESTED_BOLD); from_bold_text = 1; /* Llegado al último _, cerramos }, volvemos al stado BOLD_TEXT y ponemos from_italic_text a 1 para saber que estuvimos aquí, y no cerra antes de tiempo el \textbf*/
}
.|\n {ECHO;}
%%
/*----- Sección de Procedimientos --------*/
int main (int argc, char *argv[]) {
if (argc == 2) {
yyin = fopen (argv[1], "rt");
if (yyin == NULL) {
printf ("El fichero %s no se puede abrir\n", argv[1]);
exit (-1);
}
} else
yyin = stdin;
yyout = fopen("/tmp/out1", "wt");
if (yyout == NULL) {
printf ("El fichero %s no se puede abrir\n", argv[1]);
exit (-1);
}
yylex ();
return 0;
}
答案 0 :(得分:1)
您可以使用单个遍历和堆栈来执行多次遍历:
%option stack
并使用
更改BEGIN state
yy_push_state(STATE) // ... push current-state; BEGIN STATE
yy_pop_state // instead of BEGIN INITIAL we "return" to prev. state
这种方式很容易拥有嵌套命令
{list} { yy_push_state(IN_MARKDOWN_LIST);fprintf(yyout, "\\begin{itemize}\n");}
<IN_MARKDOWN_LIST>{
^\n { yy_pop_state(); fprintf(yyout, "\\end{itemize}\n\n");
"__" { yy_push_state(BOLD); fprintf(yyout, "\\textbf{");
"_" { yy_push_state(ITALIC); fprintf(yyout, "\\textit{");
...
}
<ITALIC>{
"_" { yy_pop_state(); fprintf(yyout, "}"); }
....
. { fprintf(yyout, "%s",yytext);}
}
答案 1 :(得分:0)
我终于找到了解决方案。我不知道它是否是最好的,但它确实有效。我像这样实施了yywrap
:
int yywrap(){
if (first_run == 1){
first_run++;
fclose(yyout);
fclose(yyin);
yyin = fopen ("/tmp/out", "rt");
yyout = fopen("salida", "wt");
if (yyin == NULL) {
printf ("El fichero no se puede abrir\n");
exit (-1);
}
if (yyout == NULL) {
printf ("El fichero no se puede abrir\n");
exit (-1);
}
return 0;
} else {
return 1;
}
}
int main (int argc, char *argv[]) {
yyin = fopen (argv[1], "rt");
// ...
yyout = fopen("/tmp/out", "wt");
// .....
yylex();
}