I am trying to do a conversor from markdown syntax to Latex and vice versa. But I am facing a problem I can not solve so far. Lets say, we have the following text:
* item
* item
* _Italic_ item
* Item with __nested _italic_ text__
Right now, my lex program would do this to the text:
\begin{itemize}
\item{item}
\item{item}
\item{_Italic_ item}
\item{Item with __nested _italic_ text__}
\end{itemize}
And, if I run the program again on that output, I get:
\begin{itemize}
\item{item}
\item{item}
\item{\textit{Italic} item}
\item{Item with nested \textit{italic} text}}
\end{itemize}
Which is the expected result, But it is supposed to do it in one run.
I want to know if it is possible to indicate Flex to run yylex() again on the output. Reading the documentation I've found something about Reentrant C Scanners and Multiple Input Buffers, but I do not know if that would solve my problem.
What is the best solution? Reentrant scanners, multiple Input buffers, or something more simpler?
I also thought on implementing the function yywrap to tell lex launch the scanner again, but with no luck:
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;
}
}
Here is my code:
/*----- 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;
}
Instead of doing multiple traversals you do it with a single traversal and stacks:
%option stack
and change BEGIN state with
yy_push_state(STATE) // ... push current-state; BEGIN STATE
yy_pop_state // instead of BEGIN INITIAL we "return" to prev. state
This way easily have nested commands
{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);}
}
I finally came out with a solution. I do not know if it is the best, but it worked. I implemented yywrap like this:
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();
}
Related
I have a problem with my code.
I send a number but the format does not working.
My code is the next.
class SetValueClass extends HelperClass {
SetValueClass() : super();
String transformValue({
required double number,
bool? pasa,
}) {
number = 27126677097.04;
SuffixOptions suffixOptions = getSuffixObject(number);
if (pasa != null && pasa) {
print(number);
print(suffixOptions.name);
print(suffixOptions.format);
print(suffixOptions.number);
print(suffixOptions.suffix);
}
final numberFormat = NumberFormat.currency(
locale: 'es_CO',
// customPattern: '',
symbol: suffixOptions.suffix,
);
numberFormat.maximumFractionDigits = suffixOptions.format['maximumFractionDigits']!;
numberFormat.minimumFractionDigits = suffixOptions.format['minimumFractionDigits']!;
return numberFormat.format(number);
}
}
The final result i want, is parse 27126677097.04 to 27,127 MM, but y received this...
27.126.677.097,04 MM
The symbol is working successfully, but, ¿how can i compact this number and return 27,127 MM?
Note: The locale es_CO is the code of Colombia.
Thanks!
After some research, I realized that the es_CO did not work the way I needed it to, so I decided to go with the following solution.
Create a function.
String _defineValue({required number}) {
/**
* Valor en el rango de cuatrillones.
* (C)
*/
if (number > 1e+24) {
return "${(number / 1e+24).toStringAsFixed(2)} C";
}
/**
* Valor en el rango de miles de trillones.
* (MT)
*/
if (number > 1e+21) {
return "${(number / 1e+21).toStringAsFixed(3)} MT";
}
/**
* Valor en el rango de trillones.
* (T)
*/
if (number > 1e+18) {
return "${(number / 1e+18).toStringAsFixed(2)} T";
}
/**
* Valor en el rango de miles de billones.
* (MB)
*/
if (number > 1e+15) {
return "${(number / 1e+15).toStringAsFixed(3)} MB";
}
/**
* Valor en el rango de billones.
* (MB)
*/
if (number > 1e+12) {
return "${(number / 1e+12).toStringAsFixed(2)} B";
}
/**
* Valor en el rango de miles de millones.
* (MM)
*/
if (number > 1e+9) {
return "${(number / 1e+9).toStringAsFixed(3)} MM";
}
/**
* Valor en el rango de millones.
* (M)
*/
if (number > 1e+6) {
return "${(number / 1e+6).toStringAsFixed(2)} M";
}
/**
* Valor en el rango de inferior
*/
return "${(number / 1).toStringAsFixed(0)}";
}
This function gets a number and return a String with the logic required in my case.
How do I use a controller and keyboard at the same time?
So I use an Arduino as my controller using ReadByte() as my input
Here is my script for my player
void Start()
{
controller = GetComponent<Controller2D>(); // Je krijgt toegang tot de script Controller2D
sp.DtrEnable = true;
sp.ReadTimeout = 100;
sp.Open(); // Uw serialpoort openen
}
void Update()
{
if (sp.IsOpen) // Als uw serialpoort open is
{
try
{
print(sp.ReadByte()); // Ga je de inkomende waarde lezen
}
catch (System.Exception) { }
}
if (controller.collisions.above || controller.collisions.below) // Als je een botsing hebt van boven of beneden dan ga je stoppen met springen
{
moveDistance.y = 0;
}
if (Input.GetKeyDown(KeyCode.Space) || sp.ReadByte() == 1 && controller.collisions.below) // Als je op spatie drukt en als je op een platform staat dan ga je boven springen
{
moveDistance.y = jumpDistance; // Je gaat springen langs de y-as
//moveDistance.x = 0; // Als je alleen springt dan ga je loodrecht boven en niet schuin
}
Vector2 input = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical")); // Je neemt de Horizontal en vertical inputs van de unity zelf
if (sp.ReadByte() == 2) // Als je de 2de drukknop indrukt
{
moveDistance.x = -moveSpeed ; // Ga je links bewegen
}
if (sp.ReadByte() == 3) // Als je de 3de druknop indrukt
{
moveDistance.x = moveSpeed; // Ga je rechts bewegen
}
moveDistance.x = input.x * moveSpeed; // Door input kan je nu links of rechts bewegen met de pijlen
moveDistance.y += gravity * Time.deltaTime; // Je valt met een zwaartekracht dus je gaat sneller en sneller vallen.
controller.Move(moveDistance * Time.deltaTime); // Leest de input
}
Normally I would want to have both controller and keyboard as my inputs but after I run this game I immediatly get a
TimeoutException: the operation has timed out
error but I can use the Arduino as inputs but it's just the keyboard that gets disabled for some reason
Might be the cause of the error not sure but in general I would not use sp.ReadByte() repeatedly but only once, store the value and compare that:
void Update()
{
byte arduinoInput = 0;
if (sp.IsOpen) // Als uw serialpoort open is
{
try
{
arduinoInput = sp.ReadByte();
print(arduinoInput); // Ga je de inkomende waarde lezen
}
catch (System.Exception) { }
}
if (controller.collisions.above || controller.collisions.below) // Als je een botsing hebt van boven of beneden dan ga je stoppen met springen
{
moveDistance.y = 0;
}
if (Input.GetKeyDown(KeyCode.Space) || arduinoInput == 1 && controller.collisions.below) // Als je op spatie drukt en als je op een platform staat dan ga je boven springen
{
moveDistance.y = jumpDistance; // Je gaat springen langs de y-as
//moveDistance.x = 0; // Als je alleen springt dan ga je loodrecht boven en niet schuin
}
Vector2 input = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical")); // Je neemt de Horizontal en vertical inputs van de unity zelf
if (arduinoInput == 2) // Als je de 2de drukknop indrukt
{
moveDistance.x = -moveSpeed ; // Ga je links bewegen
}
if (arduinoInput == 3) // Als je de 3de druknop indrukt
{
moveDistance.x = moveSpeed; // Ga je rechts bewegen
}
moveDistance.x = input.x * moveSpeed; // Door input kan je nu links of rechts bewegen met de pijlen
moveDistance.y += gravity * Time.deltaTime; // Je valt met een zwaartekracht dus je gaat sneller en sneller vallen.
controller.Move(moveDistance * Time.deltaTime); // Leest de input
}
The errors are probably thrown for frames when the port is not open yet bt you already tried to read or simply caused by the multiple access.
I've read on here that the /n in scanf makes the program wait for another input. my program however does not have a /n in scanf but it still waits for another input after i enter a number. Not sure why.
#include <stdio.h>
int main()
{
int inputNumber, index = 2, lowestPrime = 1, number = 1;
printf("Enter an integer: ");
scanf("%d", &inputNumber);
if(scanf("%d", &inputNumber) != 1)
{
printf("Invalid input");
return 1;
}
else
{
printf(" The prime factorization of %d is",inputNumber);
while(inputNumber > lowestPrime)
{
if(inputNumber % index != 0)
{
index += 1;
}
else
{
inputNumber = (inputNumber / index);
printf(" %d", index);
}
}
}
return 0;
}
You're calling scanf twice here, once for the original call and once in your if statement. Replace the statement inside the if parenthesis by
if (inputNumber!= 1)
and you should be fine!
Can you tell me what's wrong in this piece of code? It does not call the Invoke function
public class ReazioneBonus : MonoBehaviour {
void OnTriggerEnter(Collider collider){
string nomeBonus;
if(collider.gameObject.name.Contains("Pallina")){
nomeBonus = gameObject.name;
Debug.Log("bonus colpito");
Debug.Log("il nome del bonus è " + nomeBonus);
if(nomeBonus == "PaddleLungo(Clone)"){ //Allunga il paddle per 5 secondi
Debug.Log("attivazione Paddle Lungo");
Destroy(gameObject);
Debug.Log("bonus colpito da " + Pallina.ultimoGiocatoreToccato);
if(Pallina.ultimoGiocatoreToccato.name == "AvversarioRosso" || Pallina.ultimoGiocatoreToccato.name == "AvversarioVerde"){
Debug.Log("giocatore riconosciuto");
AllungaPaddleVerticale();
Invoke ("RipristinaPadVerticale", 5f); //non chiama la funzione
}else if(Pallina.ultimoGiocatoreToccato.name == "AvversarioBlu" || Pallina.ultimoGiocatoreToccato.name == "AvversarioGiallo"){
Debug.Log("giocatore riconosciuto");
AllungaPaddleOrizzontale();
Invoke ("RipristinaPadOrizzontale", 5f); //non chiama la funzione
}
}
}
}
void AllungaPaddleVerticale(){
Pallina.ultimoGiocatoreToccato.transform.localScale += new Vector3(3F, 0, 0);
}
void AllungaPaddleOrizzontale(){
Pallina.ultimoGiocatoreToccato.transform.localScale += new Vector3(0, 0, 3F);
}
void RipristinaPadVerticale(){
Debug.Log("ripristino il paddle");
Pallina.ultimoGiocatoreToccato.transform.localScale += new Vector3(-3F, 0, 0);
}
void RipristinaPadOrizzontale(){
Debug.Log("ripristino il paddle");
Pallina.ultimoGiocatoreToccato.transform.localScale += new Vector3(0, 0, -3F);
}
}
You destroy the gameObject of that monobehavior:
Destroy(gameObject);
How would these methods be invoked if the monobehavior itself is already destroyed?
When you destroy a GameObject all attached MonoBehaviours' active invokes are cancelled. This to prevent bad references.
Simply destroy the GameObject after your invokes are complete:
public class ReazioneBonus : MonoBehaviour {
void OnTriggerEnter(Collider collider){
string nomeBonus;
if(collider.gameObject.name.Contains("Pallina")){
nomeBonus = gameObject.name;
Debug.Log("bonus colpito");
Debug.Log("il nome del bonus è " + nomeBonus);
if(nomeBonus == "PaddleLungo(Clone)"){ //Allunga il paddle per 5 secondi
Debug.Log("attivazione Paddle Lungo");
Debug.Log("bonus colpito da " + Pallina.ultimoGiocatoreToccato);
if(Pallina.ultimoGiocatoreToccato.name == "AvversarioRosso" || Pallina.ultimoGiocatoreToccato.name == "AvversarioVerde"){
Debug.Log("giocatore riconosciuto");
AllungaPaddleVerticale();
Invoke ("RipristinaPadVerticale", 5f); //non chiama la funzione
}else if(Pallina.ultimoGiocatoreToccato.name == "AvversarioBlu" || Pallina.ultimoGiocatoreToccato.name == "AvversarioGiallo"){
Debug.Log("giocatore riconosciuto");
AllungaPaddleOrizzontale();
Invoke ("RipristinaPadOrizzontale", 5f); //non chiama la funzione
}
}
}
}
void AllungaPaddleVerticale(){
Pallina.ultimoGiocatoreToccato.transform.localScale += new Vector3(3F, 0, 0);
}
void AllungaPaddleOrizzontale(){
Pallina.ultimoGiocatoreToccato.transform.localScale += new Vector3(0, 0, 3F);
}
void RipristinaPadVerticale(){
Debug.Log("ripristino il paddle");
Pallina.ultimoGiocatoreToccato.transform.localScale += new Vector3(-3F, 0, 0);
Destroy(gameObject);
}
void RipristinaPadOrizzontale(){
Debug.Log("ripristino il paddle");
Pallina.ultimoGiocatoreToccato.transform.localScale += new Vector3(0, 0, -3F);
Destroy(gameObject);
}
}
Could anyone please help me in writing a LEX program to check and count comment lines in a C program. I have searched for it everywhere and failed to get the complete code.
comment lines are of the form
%%
{START} {whatever symbols,alphanumerics and letters} {END}
%%
START symbol can be // or /* in C.
END symbol is */
If it is "//" any other symbol can follow it in the LINE including a second occurances of // (which is ignored).
IF it is " /* " it will find the next immediate match for " */ " and all the rest of the patterns that appear in between is matched(This matching may include blank spaces,tabs ,"//" and " /* " in it)
Here is a sample code to do it
`
%{
#include<stdio.h>
int c=0;
%}
START "/*"
END "*/"
SIMPLE [^*]
SPACE [ \t\n]
COMPLEX "*"[^/]
%s newstate
%%
"//"(.*[ \t]*.*)*[\n]+ {c++; fprintf(yyout," ");}
{START} {yymore();BEGIN newstate;}
<newstate>{SIMPLE} {yymore();BEGIN newstate;}
<newstate>{COMPLEX} {yymore();BEGIN newstate;}
<newstate>{SPACE} {yymore();BEGIN newstate;}
<newstate>{END} {c++;fprintf(yyout," ");BEGIN 0;}
%%
main()
{//program to remove comment lines
yyin=fopen("file4","r");
yyout=fopen("fileout4","w");system("cat file4");
yylex();system("cat fileout4");
printf("no.of comments=%d",c);
fclose(yyin);
fclose(yyout);
}
`
The input file "file4" is below
/* #include <stdlib.h>
{}.#All nonsense symbols */
//another comment
int main{}
{/**/
printf("hello");
/* comment inside// comment is ignored */
//how about//this?
/* now we /* try this */ */
printf("COOL!!");
return (0);
}
It gives the following output which is stored in "fileout4" `
int main{}
{
printf("hello");
*/
printf("COOL!!");
return (0);
}
`
The number of comment lines in the above program is 6.
You can maintain a boolean variable which keeps track of whether the line you're parsing is inside a multi-line comment or not.
%{
#include <stdio.h>
#include <stdbool.h>
int comment_lines = 0;
bool in_comment = false;
%}
%%
"/*".*\n { in_comment = true; ++comment_lines; }
.*"*/"\n { in_comment = false; ++comment_lines; }
"//".*\n { ++comment_lines; }
.*\n {
if (in_comment) {
++comment_lines;
} else {
fprintf(yyout, yytext);
}
}
%%
int yywrap() {
return 1;
}
int main(void) {
printf("Enter input file: ");
char filename[64];
scanf("%s", filename);
yyin = fopen(filename, "r");
printf("Enter output file: ");
scanf("%s", filename);
yyout = fopen(filename, "w");
yylex();
printf("Number of comments: %d\n", comment_lines);
}
In the above code, in_comment is used to indicate the state of the line being analyzed. If it is in a comment, the comment_lines value is incremented, otherwise the text is written to an output file given by yyout.
input file
#include <stdio.h>
/*
*
* This is a multi-line comment
*
*/
void dummy();
// main function is the entry point.
int main(void) {
/*
* Here we print a message on user's
* console.
*/
printf("Hello world\n");
// That is it.
}
output file generated after lexical analysis
#include <stdio.h>
void dummy();
int main(void) {
printf("Hello world\n");
}
Number of comments: 11
%{
#undef yywrap
#define yywrap() 1
int single=0, multiline =0;
%}
%%
"//".*"\n" {printf("%s\n", yytext); single++;}
"/*".*[\n]*.*"*/" {printf("%s\n", yytext); multiline++;}
.;
%%
int main()
{
yyin = fopen("yourfile","r");
yylex(); //calling the rules section
printf(" Single line comments = %d, multiline comments = %d", single, multiline);
fclose(yyin);
}