You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1698 lines
31 KiB
1698 lines
31 KiB
//*****************************************************************
|
|
//
|
|
// $file: main.cpp $
|
|
// $author: Martin Fouilleul $
|
|
// $date: 23/12/2017 $
|
|
//
|
|
//*****************************************************************
|
|
|
|
/*
|
|
------------------------------------------------------------------------------
|
|
This software is available under 2 licenses -- choose whichever you prefer.
|
|
------------------------------------------------------------------------------
|
|
ALTERNATIVE A - MIT License
|
|
Copyright (c) 2017 Martin Fouilleul
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
this software and associated documentation files (the "Software"), to deal in
|
|
the Software without restriction, including without limitation the rights to
|
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
of the Software, and to permit persons to whom the Software is furnished to do
|
|
so, subject to the following conditions:
|
|
The above copyright notice and this permission notice shall be included in all
|
|
copies or substantial portions of the Software.
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
SOFTWARE.
|
|
------------------------------------------------------------------------------
|
|
ALTERNATIVE B - Public Domain (www.unlicense.org)
|
|
This is free and unencumbered software released into the public domain.
|
|
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
|
|
software, either in source code form or as a compiled binary, for any purpose,
|
|
commercial or non-commercial, and by any means.
|
|
In jurisdictions that recognize copyright laws, the author or authors of this
|
|
software dedicate any and all copyright interest in the software to the public
|
|
domain. We make this dedication for the benefit of the public at large and to
|
|
the detriment of our heirs and successors. We intend this dedication to be an
|
|
overt act of relinquishment in perpetuity of all present and future rights to
|
|
this software under copyright law.
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
------------------------------------------------------------------------------
|
|
*/
|
|
|
|
#include<stdio.h>
|
|
#include<strings.h>
|
|
|
|
#include"scanner.h"
|
|
|
|
int section = 0;
|
|
int enterCount = 0;
|
|
|
|
bool underline = false;
|
|
bool bold = false;
|
|
bool italic = false;
|
|
bool regular = false;
|
|
bool paragraph = false;
|
|
bool ldquo = false;
|
|
|
|
FILE* input = 0;
|
|
FILE* output = 0;
|
|
|
|
|
|
int HighlightCode(FILE* in, FILE* out);
|
|
|
|
void EvalMarkup(token* t);
|
|
void EvalTag(token* t);
|
|
void EvalEsc(token* t);
|
|
|
|
|
|
void EatSpaceUntilEndl(FILE* input, token* t)
|
|
{
|
|
GetNextToken(input, t);
|
|
while(t->type == CHAR && (t->c == ' ' || t->c == '\t'))
|
|
{
|
|
GetNextToken(input, t);
|
|
}
|
|
if(t->type == ENDL)
|
|
{
|
|
GetNextToken(input, t);
|
|
}
|
|
}
|
|
|
|
void EvalCharInCodeMode(token* t)
|
|
{
|
|
//NOTE(martin): replaces special characters with html entities
|
|
|
|
switch(t->c)
|
|
{
|
|
case '<':
|
|
fprintf(output, "<");
|
|
break;
|
|
|
|
case '>':
|
|
fprintf(output, ">");
|
|
break;
|
|
|
|
case '&':
|
|
fprintf(output, "&");
|
|
break;
|
|
|
|
default:
|
|
putc(t->c, output);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void EvalChar(token* t)
|
|
{
|
|
//NOTE(martin): replaces special characters with html entities
|
|
|
|
switch(t->c)
|
|
{
|
|
case '<':
|
|
fprintf(output, "<");
|
|
break;
|
|
|
|
case '>':
|
|
fprintf(output, ">");
|
|
break;
|
|
|
|
case '&':
|
|
fprintf(output, "&");
|
|
break;
|
|
|
|
case '"':
|
|
if(!ldquo)
|
|
{
|
|
fprintf(output, "“");
|
|
ldquo = true;
|
|
}
|
|
else
|
|
{
|
|
fprintf(output, "”");
|
|
ldquo = false;
|
|
}
|
|
break;
|
|
|
|
case '\t':
|
|
fprintf(output, "<span style=\"white-space:pre;\">\t</span>");
|
|
break;
|
|
|
|
default:
|
|
putc(t->c, output);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void EvalSymbol(token* t)
|
|
{
|
|
switch(t->symbol.code)
|
|
{
|
|
case MULTIPLY:
|
|
fprintf(output, "×");
|
|
break;
|
|
case DIVIDE:
|
|
fprintf(output, "÷");
|
|
break;
|
|
case SUBSTRACT:
|
|
fprintf(output, "−");
|
|
break;
|
|
case STAR:
|
|
fprintf(output, "*");
|
|
break;
|
|
case LOSTAR:
|
|
fprintf(output, "∗");
|
|
break;
|
|
case CDOT:
|
|
fprintf(output, "·");
|
|
break;
|
|
case LEQ:
|
|
fprintf(output, "≤");
|
|
break;
|
|
case GEQ:
|
|
fprintf(output, "≥");
|
|
break;
|
|
case INF:
|
|
fprintf(output, "∞");
|
|
break;
|
|
case OTIMES:
|
|
fprintf(output, "⊗");
|
|
break;
|
|
case LARR:
|
|
fprintf(output, "←");
|
|
break;
|
|
case RARR:
|
|
fprintf(output, "→");
|
|
break;
|
|
case EMDASH:
|
|
fprintf(output, "—");
|
|
break;
|
|
case LINE:
|
|
fprintf(output, "<hr/>");
|
|
break;
|
|
case THINSPACE:
|
|
fprintf(output, " ");
|
|
break;
|
|
case ALPHA:
|
|
fprintf(output, "α");
|
|
break;
|
|
case BETA:
|
|
fprintf(output, "β");
|
|
break;
|
|
case GAMMA:
|
|
fprintf(output, "γ");
|
|
break;
|
|
case DELTA:
|
|
fprintf(output, "δ");
|
|
break;
|
|
case EPSILON:
|
|
fprintf(output, "ε");
|
|
break;
|
|
case ZETA:
|
|
fprintf(output, "ζ");
|
|
break;
|
|
case ETA:
|
|
fprintf(output, "η");
|
|
break;
|
|
case THETA:
|
|
fprintf(output, "θ");
|
|
break;
|
|
case IOTA:
|
|
fprintf(output, "ι");
|
|
break;
|
|
case KAPPA:
|
|
fprintf(output, "κ");
|
|
break;
|
|
case LAMBDA:
|
|
fprintf(output, "λ");
|
|
break;
|
|
case MU:
|
|
fprintf(output, "μ");
|
|
break;
|
|
case NU:
|
|
fprintf(output, "ν");
|
|
break;
|
|
case XI:
|
|
fprintf(output, "ξ");
|
|
break;
|
|
case OMICRON:
|
|
fprintf(output, "ο");
|
|
break;
|
|
case PI:
|
|
fprintf(output, "π");
|
|
break;
|
|
case RHO:
|
|
fprintf(output, "ρ");
|
|
break;
|
|
case SIGMA:
|
|
fprintf(output, "σ");
|
|
break;
|
|
case TAU:
|
|
fprintf(output, "τ");
|
|
break;
|
|
case UPSILON:
|
|
fprintf(output, "υ");
|
|
break;
|
|
case PHI:
|
|
fprintf(output, "φ");
|
|
break;
|
|
case CHI:
|
|
fprintf(output, "χ");
|
|
break;
|
|
case PSI:
|
|
fprintf(output, "ψ");
|
|
break;
|
|
case OMEGA:
|
|
fprintf(output, "ω");
|
|
break;
|
|
case ALPHA_UPPER:
|
|
fprintf(output, "Α");
|
|
break;
|
|
case BETA_UPPER:
|
|
fprintf(output, "Β");
|
|
break;
|
|
case GAMMA_UPPER:
|
|
fprintf(output, "Γ");
|
|
break;
|
|
case DELTA_UPPER:
|
|
fprintf(output, "Δ");
|
|
break;
|
|
case EPSILON_UPPER:
|
|
fprintf(output, "Ε");
|
|
break;
|
|
case ZETA_UPPER:
|
|
fprintf(output, "Ζ");
|
|
break;
|
|
case ETA_UPPER:
|
|
fprintf(output, "Η");
|
|
break;
|
|
case THETA_UPPER:
|
|
fprintf(output, "Θ");
|
|
break;
|
|
case IOTA_UPPER:
|
|
fprintf(output, "Ι");
|
|
break;
|
|
case KAPPA_UPPER:
|
|
fprintf(output, "Κ");
|
|
break;
|
|
case LAMBDA_UPPER:
|
|
fprintf(output, "Λ");
|
|
break;
|
|
case MU_UPPER:
|
|
fprintf(output, "Μ");
|
|
break;
|
|
case NU_UPPER:
|
|
fprintf(output, "Ν");
|
|
break;
|
|
case XI_UPPER:
|
|
fprintf(output, "Ξ");
|
|
break;
|
|
case OMICRON_UPPER:
|
|
fprintf(output, "Ο");
|
|
break;
|
|
case PI_UPPER:
|
|
fprintf(output, "Π");
|
|
break;
|
|
case RHO_UPPER:
|
|
fprintf(output, "Ρ");
|
|
break;
|
|
case SIGMA_UPPER:
|
|
fprintf(output, "Σ");
|
|
break;
|
|
case TAU_UPPER:
|
|
fprintf(output, "Τ");
|
|
break;
|
|
case UPSILON_UPPER:
|
|
fprintf(output, "Υ");
|
|
break;
|
|
case PHI_UPPER:
|
|
fprintf(output, "Φ");
|
|
break;
|
|
case CHI_UPPER:
|
|
fprintf(output, "Χ");
|
|
break;
|
|
case PSI_UPPER:
|
|
fprintf(output, "Ψ");
|
|
break;
|
|
case OMEGA_UPPER:
|
|
fprintf(output, "Ω");
|
|
break;
|
|
}
|
|
}
|
|
|
|
void EvalURL(token* t)
|
|
{
|
|
fprintf(output, "<a href=\"%s\">", t->markup.text);
|
|
GetNextToken(input, t);
|
|
while(t->type != ENDF)
|
|
{
|
|
switch(t->type)
|
|
{
|
|
case ESC:
|
|
EvalEsc(t);
|
|
break;
|
|
case MARKUP:
|
|
if( t->markup.type == CODE_BLOCK_START
|
|
|| t->markup.type == MATHS_BLOCK_START
|
|
|| t->markup.type == HTML_BLOCK_START
|
|
|| t->markup.type == LIST)
|
|
{
|
|
//error
|
|
return;
|
|
}
|
|
else if(t->markup.type == URL_STOP)
|
|
{
|
|
fprintf(output, "</a>\n");
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
EvalMarkup(t);
|
|
}
|
|
break;
|
|
case HTML_TAG:
|
|
EvalTag(t);
|
|
break;
|
|
case ENDL:
|
|
fprintf(output, "<br>\n");
|
|
break;
|
|
|
|
case SYMBOL:
|
|
EvalSymbol(t);
|
|
break;
|
|
|
|
case CHAR: default:
|
|
EvalChar(t);
|
|
break;
|
|
}
|
|
GetNextToken(input, t);
|
|
}
|
|
//error
|
|
}
|
|
|
|
void EvalImage(token* t)
|
|
{
|
|
fprintf(output, "<img src=\"%s\">", t->markup.text);
|
|
}
|
|
|
|
void EvalMathsChar(token* t)
|
|
{
|
|
//NOTE(martin): replaces special characters with html entities
|
|
|
|
switch(t->c)
|
|
{
|
|
case '<':
|
|
fprintf(output, "<span class=\"rel\"><</span>");
|
|
break;
|
|
|
|
case '>':
|
|
fprintf(output, "<span class=\"rel\">></span>");
|
|
break;
|
|
|
|
case '&':
|
|
fprintf(output, "&");
|
|
break;
|
|
|
|
case '\t':
|
|
fprintf(output, "  ");
|
|
break;
|
|
|
|
case '+': case '/' : case '*': case '!': case '=':
|
|
fprintf(output, "<span class=\"op\"> %c </span>", t->c);
|
|
break;
|
|
|
|
case '(': case ')' : case '[' : case ']': case ',': case ';':
|
|
fprintf(output, "<span class=\"delim\">%c</span>", t->c);
|
|
break;
|
|
|
|
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
|
|
fprintf(output, "<span class=\"digit\">%c</span>", t->c);
|
|
break;
|
|
|
|
default:
|
|
if(t->c >= 'A' && t->c <= 'Z' && !italic)
|
|
{
|
|
fprintf(output, "<span class=\"regular\">%c</span>", t->c);
|
|
}
|
|
else
|
|
{
|
|
putc(t->c, output);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void EvalMathsSymbol(token* t)
|
|
{
|
|
switch(t->symbol.code)
|
|
{
|
|
case MULTIPLY:
|
|
fprintf(output, "<span class=\"op\"> × </span>");
|
|
break;
|
|
case DIVIDE:
|
|
fprintf(output, "<span class=\"op\"> ÷ </span>");
|
|
break;
|
|
case SUBSTRACT:
|
|
fprintf(output, "<span class=\"op\"> − </span>");
|
|
break;
|
|
case STAR:
|
|
fprintf(output, "<span class=\"op\"> * </span>");
|
|
break;
|
|
case LOSTAR:
|
|
fprintf(output, "<span class=\"op\"> ∗ </span>");
|
|
break;
|
|
case CDOT:
|
|
fprintf(output, "<span class=\"op\"> · </span>");
|
|
break;
|
|
case LEQ:
|
|
fprintf(output, "<span class=\"rel\">≤</span>");
|
|
break;
|
|
case GEQ:
|
|
fprintf(output, "<span class=\"rel\">≥</span>");
|
|
break;
|
|
case INF:
|
|
fprintf(output, "<span class=\"symbol\">∞</span>");
|
|
break;
|
|
case OTIMES:
|
|
fprintf(output, "<span class=\"op\"> ⊗ </span>");
|
|
break;
|
|
case LARR:
|
|
fprintf(output, "<span class=\"delim\">←</span>");
|
|
break;
|
|
case RARR:
|
|
fprintf(output, "<span class=\"delim\">→</span>");
|
|
break;
|
|
case EMDASH:
|
|
fprintf(output, "—");
|
|
break;
|
|
case LINE:
|
|
fprintf(output, "<hr/>");
|
|
break;
|
|
case THINSPACE:
|
|
fprintf(output, " ");
|
|
break;
|
|
case ALPHA:
|
|
fprintf(output, "<span class=\"greek-letter\">α</span>");
|
|
break;
|
|
case BETA:
|
|
fprintf(output, "<span class=\"greek-letter\">β</span>");
|
|
break;
|
|
case GAMMA:
|
|
fprintf(output, "<span class=\"greek-letter\">γ</span>");
|
|
break;
|
|
case DELTA:
|
|
fprintf(output, "<span class=\"greek-letter\">δ</span>");
|
|
break;
|
|
case EPSILON:
|
|
fprintf(output, "<span class=\"greek-letter\">ε</span>");
|
|
break;
|
|
case ZETA:
|
|
fprintf(output, "<span class=\"greek-letter\">ζ</span>");
|
|
break;
|
|
case ETA:
|
|
fprintf(output, "<span class=\"greek-letter\">η</span>");
|
|
break;
|
|
case THETA:
|
|
fprintf(output, "<span class=\"greek-letter\">θ</span>");
|
|
break;
|
|
case IOTA:
|
|
fprintf(output, "<span class=\"greek-letter\">ι</span>");
|
|
break;
|
|
case KAPPA:
|
|
fprintf(output, "<span class=\"greek-letter\">κ</span>");
|
|
break;
|
|
case LAMBDA:
|
|
fprintf(output, "<span class=\"greek-letter\">λ</span>");
|
|
break;
|
|
case MU:
|
|
fprintf(output, "<span class=\"greek-letter\">μ</span>");
|
|
break;
|
|
case NU:
|
|
fprintf(output, "<span class=\"greek-letter\">ν</span>");
|
|
break;
|
|
case XI:
|
|
fprintf(output, "<span class=\"greek-letter\">ξ</span>");
|
|
break;
|
|
case OMICRON:
|
|
fprintf(output, "<span class=\"greek-letter\">ο</span>");
|
|
break;
|
|
case PI:
|
|
fprintf(output, "<span class=\"greek-letter\">π</span>");
|
|
break;
|
|
case RHO:
|
|
fprintf(output, "<span class=\"greek-letter\">ρ</span>");
|
|
break;
|
|
case SIGMA:
|
|
fprintf(output, "<span class=\"greek-letter\">σ</span>");
|
|
break;
|
|
case TAU:
|
|
fprintf(output, "<span class=\"greek-letter\">τ</span>");
|
|
break;
|
|
case UPSILON:
|
|
fprintf(output, "<span class=\"greek-letter\">υ</span>");
|
|
break;
|
|
case PHI:
|
|
fprintf(output, "<span class=\"greek-letter\">φ</span>");
|
|
break;
|
|
case CHI:
|
|
fprintf(output, "<span class=\"greek-letter\">χ</span>");
|
|
break;
|
|
case PSI:
|
|
fprintf(output, "<span class=\"greek-letter\">ψ</span>");
|
|
break;
|
|
case OMEGA:
|
|
fprintf(output, "<span class=\"greek-letter\">ω</span>");
|
|
break;
|
|
|
|
case ALPHA_UPPER:
|
|
fprintf(output, "<span class=\"greek-letter\">Α</span>");
|
|
break;
|
|
case BETA_UPPER:
|
|
fprintf(output, "<span class=\"greek-letter\">Β</span>");
|
|
break;
|
|
case GAMMA_UPPER:
|
|
fprintf(output, "<span class=\"greek-letter\">Γ</span>");
|
|
break;
|
|
case DELTA_UPPER:
|
|
fprintf(output, "<span class=\"greek-letter\">Δ</span>");
|
|
break;
|
|
case EPSILON_UPPER:
|
|
fprintf(output, "<span class=\"greek-letter\">Ε</span>");
|
|
break;
|
|
case ZETA_UPPER:
|
|
fprintf(output, "<span class=\"greek-letter\">Ζ</span>");
|
|
break;
|
|
case ETA_UPPER:
|
|
fprintf(output, "<span class=\"greek-letter\">Η</span>");
|
|
break;
|
|
case THETA_UPPER:
|
|
fprintf(output, "<span class=\"greek-letter\">Θ</span>");
|
|
break;
|
|
case IOTA_UPPER:
|
|
fprintf(output, "<span class=\"greek-letter\">Ι</span>");
|
|
break;
|
|
case KAPPA_UPPER:
|
|
fprintf(output, "<span class=\"greek-letter\">Κ</span>");
|
|
break;
|
|
case LAMBDA_UPPER:
|
|
fprintf(output, "<span class=\"greek-letter\">Λ</span>");
|
|
break;
|
|
case MU_UPPER:
|
|
fprintf(output, "<span class=\"greek-letter\">Μ</span>");
|
|
break;
|
|
case NU_UPPER:
|
|
fprintf(output, "<span class=\"greek-letter\">Ν</span>");
|
|
break;
|
|
case XI_UPPER:
|
|
fprintf(output, "<span class=\"greek-letter\">Ξ</span>");
|
|
break;
|
|
case OMICRON_UPPER:
|
|
fprintf(output, "<span class=\"greek-letter\">Ο</span>");
|
|
break;
|
|
case PI_UPPER:
|
|
fprintf(output, "<span class=\"greek-letter\">Π</span>");
|
|
break;
|
|
case RHO_UPPER:
|
|
fprintf(output, "<span class=\"greek-letter\">Ρ</span>");
|
|
break;
|
|
case SIGMA_UPPER:
|
|
fprintf(output, "<span class=\"greek-letter\">Σ</span>");
|
|
break;
|
|
case TAU_UPPER:
|
|
fprintf(output, "<span class=\"greek-letter\">Τ</span>");
|
|
break;
|
|
case UPSILON_UPPER:
|
|
fprintf(output, "<span class=\"greek-letter\">Υ</span>");
|
|
break;
|
|
case PHI_UPPER:
|
|
fprintf(output, "<span class=\"greek-letter\">Φ</span>");
|
|
break;
|
|
case CHI_UPPER:
|
|
fprintf(output, "<span class=\"greek-letter\">Χ</span>");
|
|
break;
|
|
case PSI_UPPER:
|
|
fprintf(output, "<span class=\"greek-letter\">Ψ</span>");
|
|
break;
|
|
case OMEGA_UPPER:
|
|
fprintf(output, "<span class=\"greek-letter\">Ω</span>");
|
|
break;
|
|
}
|
|
}
|
|
|
|
void EvalEsc(token* t)
|
|
{
|
|
switch(t->c)
|
|
{
|
|
case '\n':
|
|
fprintf(output, "\n");
|
|
break;
|
|
|
|
case 'n':
|
|
fprintf(output, "<br>\n");
|
|
break;
|
|
|
|
case 't':
|
|
fprintf(output, "  ");
|
|
break;
|
|
|
|
case 's': case ' ':
|
|
fprintf(output, " ");
|
|
break;
|
|
case '&':
|
|
putc('&', output);
|
|
break;
|
|
default:
|
|
EvalChar(t);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void EvalSection(token* t)
|
|
{
|
|
int sectionLevel = t->markup.value;
|
|
|
|
fprintf(output, "<h%i>", sectionLevel);
|
|
|
|
GetNextToken(input, t);
|
|
while(t->type != ENDF)
|
|
{
|
|
switch(t->type)
|
|
{
|
|
case ESC:
|
|
EvalEsc(t);
|
|
break;
|
|
case MARKUP:
|
|
if( t->markup.type == CODE_BLOCK_START
|
|
|| t->markup.type == MATHS_BLOCK_START
|
|
|| t->markup.type == HTML_BLOCK_START
|
|
|| t->markup.type == LIST)
|
|
{
|
|
//error
|
|
return;
|
|
}
|
|
else if(t->markup.type == SECTION)
|
|
{
|
|
if(t->markup.value != sectionLevel)
|
|
{
|
|
//error
|
|
}
|
|
fprintf(output, "</h%i>\n", sectionLevel);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
EvalMarkup(t);
|
|
}
|
|
break;
|
|
case HTML_TAG:
|
|
EvalTag(t);
|
|
break;
|
|
case ENDL:
|
|
fprintf(output, "<br>\n");
|
|
break;
|
|
|
|
case SYMBOL:
|
|
EvalSymbol(t);
|
|
break;
|
|
|
|
case CHAR: default:
|
|
EvalChar(t);
|
|
break;
|
|
}
|
|
GetNextToken(input, t);
|
|
}
|
|
}
|
|
|
|
void EvalBold()
|
|
{
|
|
if(!bold)
|
|
{
|
|
fprintf(output, "<b>");
|
|
bold = true;
|
|
}
|
|
else
|
|
{
|
|
fprintf(output, "</b>");
|
|
bold = false;
|
|
}
|
|
}
|
|
void EvalItalic()
|
|
{
|
|
if(!italic)
|
|
{
|
|
fprintf(output, "<i>");
|
|
italic = true;
|
|
}
|
|
else
|
|
{
|
|
fprintf(output, "</i>");
|
|
italic = false;
|
|
}
|
|
}
|
|
|
|
void EvalUnderline()
|
|
{
|
|
if(!underline)
|
|
{
|
|
fprintf(output, "<u>");
|
|
underline = true;
|
|
}
|
|
else
|
|
{
|
|
fprintf(output, "</u>");
|
|
underline = false;
|
|
}
|
|
}
|
|
|
|
void EvalRegular()
|
|
{
|
|
if(!regular)
|
|
{
|
|
fprintf(output, "<span class=\"regular\">");
|
|
regular = true;
|
|
}
|
|
else
|
|
{
|
|
fprintf(output, "</span>");
|
|
regular = false;
|
|
}
|
|
}
|
|
|
|
void EvalCode(token* t, bool inlineCode)
|
|
{
|
|
if(inlineCode || (t->markup.text && !strcmp(t->markup.text, "none")))
|
|
{
|
|
fprintf(output, "<%s class=\"code\">", inlineCode ? "span" : "div");
|
|
|
|
GetNextToken(input, t);
|
|
|
|
bool exit = false;
|
|
while(t->type != ENDF && !exit)
|
|
{
|
|
switch(t->type)
|
|
{
|
|
case MARKUP:
|
|
{
|
|
if(t->markup.type != CODE_INLINE_STOP)
|
|
{
|
|
//error;
|
|
}
|
|
exit = true;
|
|
}
|
|
break;
|
|
case CHAR:
|
|
{
|
|
EvalCharInCodeMode(t);
|
|
}
|
|
break;
|
|
default:
|
|
//error
|
|
exit = true;
|
|
break;
|
|
}
|
|
if(!exit)
|
|
{
|
|
GetNextToken(input, t);
|
|
}
|
|
}
|
|
fprintf(output, "</%s>", inlineCode ? "span" : "div");
|
|
}
|
|
else
|
|
{
|
|
fprintf(output, "<div class=\"code\">");
|
|
HighlightCode(input, output);
|
|
fprintf(output, "</div>\n");
|
|
ResetScanMode();
|
|
}
|
|
}
|
|
|
|
void EvalMaths(bool inlineMaths)
|
|
{
|
|
if(inlineMaths)
|
|
{
|
|
fprintf(output, "<span class=\"maths\">");
|
|
}
|
|
else
|
|
{
|
|
fprintf(output, "<div class=\"maths\">\n");
|
|
}
|
|
|
|
token t;
|
|
EatSpaceUntilEndl(input, &t);
|
|
|
|
while(t.type != ENDF)
|
|
{
|
|
if(t.type == MARKUP)
|
|
{
|
|
if( (!inlineMaths && t.markup.type == MATHS_BLOCK_STOP)
|
|
|| (inlineMaths && t.markup.type == MATHS_INLINE_STOP))
|
|
{
|
|
//ok
|
|
break;
|
|
}
|
|
else if( t.markup.type == MATHS_BLOCK_START
|
|
|| t.markup.type == MATHS_INLINE_START
|
|
|| t.markup.type == CODE_BLOCK_START
|
|
|| t.markup.type == CODE_INLINE_START
|
|
|| t.markup.type == HTML_BLOCK_START
|
|
|| t.markup.type == CODE_BLOCK_STOP
|
|
|| t.markup.type == CODE_INLINE_STOP
|
|
|| t.markup.type == LIST)
|
|
{
|
|
//error
|
|
break;
|
|
}
|
|
}
|
|
switch(t.type)
|
|
{
|
|
case ESC:
|
|
EvalEsc(&t);
|
|
break;
|
|
case MARKUP:
|
|
EvalMarkup(&t);
|
|
break;
|
|
case HTML_TAG:
|
|
EvalTag(&t);
|
|
break;
|
|
case ENDL:
|
|
fprintf(output, "<br>\n");
|
|
break;
|
|
case SYMBOL:
|
|
EvalMathsSymbol(&t);
|
|
break;
|
|
case CHAR: default:
|
|
EvalMathsChar(&t);
|
|
break;
|
|
}
|
|
GetNextToken(input, &t);
|
|
}
|
|
|
|
if(inlineMaths)
|
|
{
|
|
fprintf(output, "</span>");
|
|
}
|
|
else
|
|
{
|
|
fprintf(output, "</div>\n");
|
|
}
|
|
}
|
|
|
|
void EvalHTMLBlock()
|
|
{
|
|
token t;
|
|
GetNextToken(input, &t);
|
|
|
|
bool exit = false;
|
|
while(t.type != ENDF && !exit)
|
|
{
|
|
switch(t.type)
|
|
{
|
|
case MARKUP:
|
|
{
|
|
if(t.markup.type != CODE_BLOCK_STOP)
|
|
{
|
|
//error;
|
|
}
|
|
exit = true;
|
|
}
|
|
break;
|
|
case CHAR:
|
|
putc(t.c, output);
|
|
break;
|
|
default:
|
|
//error
|
|
exit = true;
|
|
break;
|
|
}
|
|
GetNextToken(input, &t);
|
|
}
|
|
}
|
|
|
|
void Indent(int level)
|
|
{
|
|
for(int i=0;i<level;i++)
|
|
{
|
|
putc('\t', output);
|
|
}
|
|
}
|
|
|
|
void EvalList(int listLevel, int destLevel)
|
|
{
|
|
while(listLevel < destLevel)
|
|
{
|
|
fprintf(output, "\n");
|
|
Indent(listLevel);
|
|
fprintf(output, "<ul>\n");
|
|
|
|
listLevel++;
|
|
|
|
Indent(listLevel);
|
|
fprintf(output, "<li>");
|
|
if(listLevel != destLevel)
|
|
{
|
|
fprintf(output, "\n");
|
|
}
|
|
}
|
|
|
|
token t;
|
|
GetNextToken(input, &t);
|
|
bool exit = false;
|
|
while(t.type != ENDF && !exit)
|
|
{
|
|
if(t.type == MARKUP && t.markup.type == LIST)
|
|
{
|
|
break;
|
|
}
|
|
switch(t.type)
|
|
{
|
|
case ESC:
|
|
EvalEsc(&t);
|
|
break;
|
|
case MARKUP:
|
|
EvalMarkup(&t);
|
|
break;
|
|
case HTML_TAG:
|
|
EvalTag(&t);
|
|
break;
|
|
case ENDL:
|
|
{
|
|
GetNextToken(input, &t);
|
|
if(t.type == ENDL)
|
|
{
|
|
exit = true;
|
|
}
|
|
else
|
|
{
|
|
if(t.type != MARKUP || t.markup.type != LIST)
|
|
{
|
|
fprintf(output, "<br>\n");
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
break;
|
|
case SYMBOL:
|
|
EvalSymbol(&t);
|
|
break;
|
|
case CHAR: default:
|
|
EvalChar(&t);
|
|
break;
|
|
}
|
|
if(!exit)
|
|
{
|
|
GetNextToken(input, &t);
|
|
}
|
|
}
|
|
|
|
if(t.type == MARKUP && t.markup.type == LIST)
|
|
{
|
|
if(t.markup.value >= listLevel)
|
|
{
|
|
if(t.markup.value == listLevel)
|
|
{
|
|
fprintf(output, "</li>\n");
|
|
Indent(listLevel);
|
|
fprintf(output, "<li>");
|
|
}
|
|
EvalList(listLevel, t.markup.value);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
fprintf(output, "</li>\n");
|
|
while(listLevel > t.markup.value )
|
|
{
|
|
listLevel--;
|
|
Indent(listLevel);
|
|
fprintf(output, "</ul>\n");
|
|
Indent(listLevel);
|
|
fprintf(output, "</li>\n");
|
|
}
|
|
if(listLevel)
|
|
{
|
|
Indent(listLevel);
|
|
fprintf(output, "<li>");
|
|
EvalList(listLevel, t.markup.value);
|
|
}
|
|
else
|
|
{
|
|
fprintf(output, "</ul>\n");
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fprintf(output, "</li>\n");
|
|
while(listLevel > 1)
|
|
{
|
|
listLevel--;
|
|
Indent(listLevel);
|
|
fprintf(output, "</ul>\n");
|
|
Indent(listLevel);
|
|
fprintf(output, "</li>\n");
|
|
}
|
|
fprintf(output, "</ul>\n");
|
|
}
|
|
}
|
|
|
|
void EvalLongSuperscript(token* t)
|
|
{
|
|
fprintf(output, "<sup>");
|
|
GetNextToken(input, t);
|
|
while(t->type != ENDF)
|
|
{
|
|
switch(t->type)
|
|
{
|
|
case ESC:
|
|
EvalEsc(t);
|
|
break;
|
|
case MARKUP:
|
|
if( t->markup.type == CODE_BLOCK_START
|
|
|| t->markup.type == MATHS_BLOCK_START
|
|
|| t->markup.type == HTML_BLOCK_START
|
|
|| t->markup.type == LIST
|
|
|| t->markup.type == SECTION)
|
|
{
|
|
//error
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
EvalMarkup(t);
|
|
}
|
|
break;
|
|
case HTML_TAG:
|
|
EvalTag(t);
|
|
break;
|
|
|
|
case SYMBOL:
|
|
EvalMathsSymbol(t);
|
|
break;
|
|
case CHAR:
|
|
if(t->c == '}')
|
|
{
|
|
fprintf(output, "</sup>");
|
|
return;
|
|
}
|
|
EvalMathsChar(t);
|
|
break;
|
|
|
|
default:
|
|
//error
|
|
return;
|
|
}
|
|
GetNextToken(input, t);
|
|
}
|
|
}
|
|
void EvalSuperscript(token* t)
|
|
{
|
|
GetNextToken(input, t);
|
|
if(t->type == CHAR && t->c == '{')
|
|
{
|
|
EvalLongSuperscript(t);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
fprintf(output, "<sup> ");
|
|
if(t->type == CHAR)
|
|
{
|
|
EvalMathsChar(t);
|
|
}
|
|
else if(t->type == SYMBOL)
|
|
{
|
|
EvalMathsSymbol(t);
|
|
}
|
|
else if(t->type == ESC)
|
|
{
|
|
EvalEsc(t);
|
|
}
|
|
else
|
|
{
|
|
//error
|
|
}
|
|
fprintf(output, "</sup>");
|
|
}
|
|
}
|
|
|
|
void EvalLongSubscript(token* t)
|
|
{
|
|
fprintf(output, "<sub>");
|
|
GetNextToken(input, t);
|
|
while(t->type != ENDF)
|
|
{
|
|
switch(t->type)
|
|
{
|
|
case ESC:
|
|
EvalEsc(t);
|
|
break;
|
|
case MARKUP:
|
|
if( t->markup.type == CODE_BLOCK_START
|
|
|| t->markup.type == MATHS_BLOCK_START
|
|
|| t->markup.type == HTML_BLOCK_START
|
|
|| t->markup.type == LIST
|
|
|| t->markup.type == SECTION)
|
|
{
|
|
//error
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
EvalMarkup(t);
|
|
}
|
|
break;
|
|
case HTML_TAG:
|
|
EvalTag(t);
|
|
break;
|
|
|
|
case SYMBOL:
|
|
EvalMathsSymbol(t);
|
|
case CHAR:
|
|
if(t->c == '}')
|
|
{
|
|
fprintf(output, "</sub>");
|
|
return;
|
|
}
|
|
EvalMathsChar(t);
|
|
break;
|
|
|
|
default:
|
|
//error
|
|
return;
|
|
}
|
|
GetNextToken(input, t);
|
|
}
|
|
}
|
|
void EvalSubscript(token* t)
|
|
{
|
|
GetNextToken(input, t);
|
|
if(t->type == CHAR && t->c == '{')
|
|
{
|
|
EvalLongSubscript(t);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
fprintf(output, "<sub>");
|
|
if(t->type == CHAR)
|
|
{
|
|
EvalMathsChar(t);
|
|
}
|
|
else if(t->type == SYMBOL)
|
|
{
|
|
EvalMathsSymbol(t);
|
|
}
|
|
else if(t->type == ESC)
|
|
{
|
|
EvalEsc(t);
|
|
}
|
|
else
|
|
{
|
|
//error
|
|
}
|
|
fprintf(output, "</sub>");
|
|
}
|
|
}
|
|
|
|
void EvalVector(token* t)
|
|
{
|
|
GetNextToken(input, t);
|
|
|
|
if(t->type == CHAR)
|
|
{
|
|
EvalMathsChar(t);
|
|
}
|
|
else if(t->type == SYMBOL)
|
|
{
|
|
EvalMathsSymbol(t);
|
|
}
|
|
else if(t->type == ESC)
|
|
{
|
|
EvalEsc(t);
|
|
}
|
|
else
|
|
{
|
|
//error
|
|
}
|
|
fprintf(output, "<span class=\"vector\">⃗</span>");
|
|
}
|
|
|
|
void EvalSqrt(token* t)
|
|
{
|
|
fprintf(output, "<span class=\"sqrt-symbol\">√</span><span class=\"sqrt-arg\"> ");
|
|
|
|
GetNextToken(input, t);
|
|
if(t->type == CHAR && t->c == '{')
|
|
{
|
|
GetNextToken(input, t);
|
|
bool exit = false;
|
|
while(t->type != ENDF && !exit)
|
|
{
|
|
switch(t->type)
|
|
{
|
|
case ESC:
|
|
EvalEsc(t);
|
|
break;
|
|
case MARKUP:
|
|
if( t->markup.type == CODE_BLOCK_START
|
|
|| t->markup.type == MATHS_BLOCK_START
|
|
|| t->markup.type == HTML_BLOCK_START
|
|
|| t->markup.type == LIST
|
|
|| t->markup.type == SECTION)
|
|
{
|
|
//error
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
EvalMarkup(t);
|
|
}
|
|
break;
|
|
case HTML_TAG:
|
|
EvalTag(t);
|
|
break;
|
|
|
|
case SYMBOL:
|
|
EvalMathsSymbol(t);
|
|
case CHAR:
|
|
if(t->c == '}')
|
|
{
|
|
exit = true;
|
|
break;
|
|
}
|
|
EvalMathsChar(t);
|
|
break;
|
|
|
|
default:
|
|
//error
|
|
return;
|
|
}
|
|
if(!exit)
|
|
{
|
|
GetNextToken(input, t);
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
if(t->type == CHAR)
|
|
{
|
|
EvalMathsChar(t);
|
|
}
|
|
else if(t->type == SYMBOL)
|
|
{
|
|
EvalMathsSymbol(t);
|
|
}
|
|
else if(t->type == ESC)
|
|
{
|
|
EvalEsc(t);
|
|
}
|
|
else
|
|
{
|
|
//error
|
|
}
|
|
}
|
|
fprintf(output, " </span>");
|
|
}
|
|
|
|
void GetMathArg(token* t)
|
|
{
|
|
GetNextToken(input, t);
|
|
bool exit = false;
|
|
while(t->type != ENDF && !exit)
|
|
{
|
|
switch(t->type)
|
|
{
|
|
case ESC:
|
|
EvalEsc(t);
|
|
break;
|
|
case MARKUP:
|
|
if( t->markup.type == CODE_BLOCK_START
|
|
|| t->markup.type == MATHS_BLOCK_START
|
|
|| t->markup.type == HTML_BLOCK_START
|
|
|| t->markup.type == LIST
|
|
|| t->markup.type == SECTION)
|
|
{
|
|
//error
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
EvalMarkup(t);
|
|
}
|
|
break;
|
|
case HTML_TAG:
|
|
EvalTag(t);
|
|
break;
|
|
|
|
case SYMBOL:
|
|
EvalMathsSymbol(t);
|
|
case CHAR:
|
|
if(t->c == '}')
|
|
{
|
|
exit = true;
|
|
break;
|
|
}
|
|
EvalMathsChar(t);
|
|
break;
|
|
|
|
default:
|
|
//error
|
|
return;
|
|
}
|
|
if(!exit)
|
|
{
|
|
GetNextToken(input, t);
|
|
}
|
|
}
|
|
}
|
|
|
|
void EvalSumProd(token* t, bool sum)
|
|
{
|
|
fprintf(output, "<span class=\"n-sum-product\">");
|
|
|
|
GetNextToken(input, t);
|
|
if(t->type == CHAR && t->c == '{')
|
|
{
|
|
GetNextToken(input, t);
|
|
|
|
if(t->type == CHAR && t->c == '{')
|
|
{
|
|
fprintf(output, "<span class=\"range-max\">");
|
|
GetMathArg(t);
|
|
fprintf(output, "</span>");
|
|
}
|
|
else
|
|
{
|
|
//error
|
|
}
|
|
|
|
fprintf(output, "<span class=\"n-op-symbol\">%s</span>", sum ? "∑" : "∏");
|
|
|
|
GetNextToken(input, t);
|
|
if(t->type == CHAR && t->c == '{')
|
|
{
|
|
fprintf(output, "<span class=\"range-min\">");
|
|
GetMathArg(t);
|
|
fprintf(output, "</span>");
|
|
}
|
|
else
|
|
{
|
|
//error
|
|
}
|
|
|
|
GetNextToken(input, t);
|
|
if(t->type != CHAR || t->c == '}')
|
|
{
|
|
//error
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//error
|
|
}
|
|
fprintf(output, "</span> ");
|
|
}
|
|
|
|
|
|
void EvalFrac(token* t)
|
|
{
|
|
fprintf(output, "<span class=\"fraction\">");
|
|
|
|
GetNextToken(input, t);
|
|
if(t->type == CHAR && t->c == '{')
|
|
{
|
|
GetNextToken(input, t);
|
|
|
|
if(t->type == CHAR && t->c == '{')
|
|
{
|
|
fprintf(output, "<span class=\"numerator\">");
|
|
GetMathArg(t);
|
|
fprintf(output, "</span>");
|
|
}
|
|
else
|
|
{
|
|
//error
|
|
}
|
|
GetNextToken(input, t);
|
|
if(t->type == CHAR && t->c == '{')
|
|
{
|
|
fprintf(output, "<span class=\"denominator\">");
|
|
GetMathArg(t);
|
|
fprintf(output, "</span>");
|
|
}
|
|
else
|
|
{
|
|
//error
|
|
}
|
|
|
|
GetNextToken(input, t);
|
|
if(t->type != CHAR || t->c == '}')
|
|
{
|
|
//error
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//error
|
|
}
|
|
fprintf(output, "</span>");
|
|
}
|
|
|
|
void EvalMarkup(token* t)
|
|
{
|
|
markup_tag* markup = &t->markup;
|
|
|
|
switch(markup->type)
|
|
{
|
|
case MATHS_INLINE_START:
|
|
EvalMaths(true);
|
|
break;
|
|
case MATHS_BLOCK_START:
|
|
EvalMaths(false);
|
|
break;
|
|
case CODE_INLINE_START:
|
|
EvalCode(t, true);
|
|
break;
|
|
case CODE_BLOCK_START:
|
|
EvalCode(t, false);
|
|
break;
|
|
case HTML_BLOCK_START:
|
|
EvalHTMLBlock();
|
|
break;
|
|
case URL_START:
|
|
EvalURL(t);
|
|
break;
|
|
case IMG:
|
|
EvalImage(t);
|
|
break;
|
|
case SECTION:
|
|
EvalSection(t);
|
|
break;
|
|
case UNDERLINE:
|
|
EvalUnderline();
|
|
break;
|
|
case BOLD:
|
|
EvalBold();
|
|
break;
|
|
case ITALIC:
|
|
EvalItalic();
|
|
break;
|
|
case REGULAR:
|
|
EvalRegular();
|
|
break;
|
|
case LIST:
|
|
EvalList(0, 1);
|
|
break;
|
|
case SUBSCRIPT:
|
|
EvalSubscript(t);
|
|
break;
|
|
case SUPERSCRIPT:
|
|
EvalSuperscript(t);
|
|
break;
|
|
case VECTOR:
|
|
EvalVector(t);
|
|
break;
|
|
case SQRT:
|
|
EvalSqrt(t);
|
|
break;
|
|
case FRACTION:
|
|
EvalFrac(t);
|
|
break;
|
|
case NSUM:
|
|
EvalSumProd(t, true);
|
|
break;
|
|
case NPRODUCT:
|
|
EvalSumProd(t, false);
|
|
break;
|
|
|
|
default:
|
|
//error
|
|
break;
|
|
}
|
|
}
|
|
|
|
void EvalTag(token* t)
|
|
{
|
|
fprintf(output, "%s", t->html.text);
|
|
}
|
|
|
|
void EvalParagraph(token* t)
|
|
{
|
|
fprintf(output, "<p>\n");
|
|
|
|
while(t->type != ENDF)
|
|
{
|
|
switch(t->type)
|
|
{
|
|
case ESC:
|
|
EvalEsc(t);
|
|
break;
|
|
case MARKUP:
|
|
if( t->markup.type == CODE_BLOCK_START
|
|
|| t->markup.type == MATHS_BLOCK_START
|
|
|| t->markup.type == HTML_BLOCK_START
|
|
|| t->markup.type == SECTION
|
|
|| t->markup.type == LIST)
|
|
{
|
|
fprintf(output, "\n</p>\n");
|
|
return;
|
|
}
|
|
EvalMarkup(t);
|
|
break;
|
|
case HTML_TAG:
|
|
EvalTag(t);
|
|
break;
|
|
case ENDL:
|
|
GetNextToken(input, t);
|
|
if(t->type == ENDL)
|
|
{
|
|
fprintf(output, "\n</p>\n");
|
|
GetNextToken(input, t);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
fprintf(output, "<br>\n");
|
|
}
|
|
continue;
|
|
|
|
case SYMBOL:
|
|
EvalSymbol(t);
|
|
break;
|
|
case CHAR: default:
|
|
EvalChar(t);
|
|
break;
|
|
}
|
|
GetNextToken(input, t);
|
|
}
|
|
fprintf(output, "\n</p>\n");
|
|
}
|
|
|
|
int main(int argc, char** argv)
|
|
{
|
|
if(argc > 1)
|
|
{
|
|
input = fopen(argv[1], "r");
|
|
}
|
|
if(argc > 2)
|
|
{
|
|
output = fopen(argv[2], "w");
|
|
}
|
|
if(!input)
|
|
{
|
|
input = stdin;
|
|
}
|
|
if(!output)
|
|
{
|
|
output = stdout;
|
|
}
|
|
|
|
token t;
|
|
GetNextToken(input, &t);
|
|
|
|
while(t.type != ENDF)
|
|
{
|
|
switch(t.type)
|
|
{
|
|
case MARKUP:
|
|
if( t.markup.type == CODE_BLOCK_START
|
|
|| t.markup.type == MATHS_BLOCK_START
|
|
|| t.markup.type == HTML_BLOCK_START)
|
|
{
|
|
EvalMarkup(&t);
|
|
|
|
//NOTE(martin): we eat the first newline after blocks
|
|
EatSpaceUntilEndl(input, &t);
|
|
continue;
|
|
}
|
|
else if(t.markup.type == SECTION)
|
|
{
|
|
EvalMarkup(&t);
|
|
|
|
//NOTE(martin): we eat the first newline after blocks
|
|
EatSpaceUntilEndl(input, &t);
|
|
EatSpaceUntilEndl(input, &t);
|
|
continue;
|
|
}
|
|
else if(t.markup.type == LIST)
|
|
{
|
|
EvalMarkup(&t);
|
|
//NOTE(martin): we eat the first newline after blocks
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
EvalParagraph(&t);
|
|
continue;
|
|
}
|
|
break;
|
|
case HTML_TAG:
|
|
EvalTag(&t);
|
|
//NOTE(martin): we eat the first newline after a block
|
|
EatSpaceUntilEndl(input, &t);
|
|
continue;
|
|
|
|
break;
|
|
case ENDL:
|
|
fprintf(output, "<br>\n");
|
|
break;
|
|
case ESC:
|
|
if(t.c == '\n')
|
|
{
|
|
EvalEsc(&t);
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
EvalParagraph(&t);
|
|
}
|
|
break;
|
|
case SYMBOL:
|
|
case CHAR: default:
|
|
EvalParagraph(&t);
|
|
continue;
|
|
break;
|
|
}
|
|
GetNextToken(input, &t);
|
|
}
|
|
|
|
if(input != stdin)
|
|
{
|
|
fclose(input);
|
|
}
|
|
if(output != stdout)
|
|
{
|
|
fclose(output);
|
|
}
|
|
return(0);
|
|
}
|
|
|