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.
858 lines
16 KiB
858 lines
16 KiB
//*****************************************************************
|
|
//
|
|
// $file: scanner.cpp $
|
|
// $author: Martin Fouilleul $
|
|
// $date: 24/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"
|
|
|
|
static int mode = MODE_TEXT;
|
|
|
|
const int MAX_LOOK_AHEAD = 15;
|
|
|
|
bool LookAhead(FILE* input, const char* string)
|
|
{
|
|
char buffer[MAX_LOOK_AHEAD+1];
|
|
int len = strlen(string);
|
|
int count = 0;
|
|
|
|
|
|
while(count<len && count<MAX_LOOK_AHEAD)
|
|
{
|
|
buffer[count] = getc(input);
|
|
if(buffer[count] != string[count])
|
|
{
|
|
break;
|
|
}
|
|
count++;
|
|
}
|
|
if(count != len)
|
|
{
|
|
//NOTE(martin): push back characters and return false
|
|
for(int i=count;i>=0;i--)
|
|
{
|
|
ungetc(buffer[i], input);
|
|
}
|
|
return(false);
|
|
}
|
|
else
|
|
{
|
|
return(true);
|
|
}
|
|
}
|
|
|
|
char Peek(FILE* input)
|
|
{
|
|
char c = getc(input);
|
|
ungetc(c, input);
|
|
return(c);
|
|
}
|
|
|
|
void CharacterToken(FILE* input, token* t)
|
|
{
|
|
t->type = CHAR;
|
|
t->c = getc(input);
|
|
}
|
|
|
|
void MarkupCharToken(markup_type type, token* t)
|
|
{
|
|
t->type = MARKUP;
|
|
t->markup.type = type;
|
|
t->markup.value = 0;
|
|
}
|
|
|
|
void SymbolToken(symbol_code code, token* t)
|
|
{
|
|
t->type = SYMBOL;
|
|
t->symbol.code = code;
|
|
}
|
|
|
|
|
|
void EndlToken(FILE* input, token* t)
|
|
{
|
|
getc(input);
|
|
t->type = ENDL;
|
|
}
|
|
|
|
void AttributedMarkupToken(FILE* input, markup_type type, token* t)
|
|
{
|
|
t->type = MARKUP;
|
|
t->markup.type = type;
|
|
int count = 0;
|
|
char c;
|
|
while(((c = getc(input)) != EOF) && count < MAX_MARKUP_TAG_LENGTH)
|
|
{
|
|
if(c==']')
|
|
{
|
|
t->markup.text[count] = '\0';
|
|
return;
|
|
}
|
|
t->markup.text[count] = c;
|
|
count++;
|
|
}
|
|
//error
|
|
return;
|
|
}
|
|
|
|
void BlockToken(FILE* input, token* t)
|
|
{
|
|
t->type = MARKUP;
|
|
|
|
if( LookAhead(input, "[c]"))
|
|
{
|
|
t->markup.type = CODE_INLINE_START;
|
|
mode = MODE_CODE_INLINE;
|
|
}
|
|
else if(LookAhead(input, "[m]"))
|
|
{
|
|
t->markup.type = MATHS_INLINE_START;
|
|
mode = MODE_MATHS_INLINE;
|
|
}
|
|
else if(LookAhead(input, "[/c]"))
|
|
{
|
|
t->markup.type = CODE_INLINE_STOP;
|
|
mode = MODE_TEXT;
|
|
}
|
|
else if(LookAhead(input, "[/m]"))
|
|
{
|
|
t->markup.type = MATHS_INLINE_STOP;
|
|
mode = MODE_TEXT;
|
|
}
|
|
else if(LookAhead(input, "[code="))
|
|
{
|
|
AttributedMarkupToken(input, CODE_BLOCK_START, t);
|
|
mode = MODE_CODE_BLOCK;
|
|
}
|
|
else if(LookAhead(input, "[code]"))
|
|
{
|
|
t->markup.type = CODE_BLOCK_START;
|
|
mode = MODE_CODE_BLOCK;
|
|
}
|
|
else if(LookAhead(input, "[html]"))
|
|
{
|
|
t->markup.type = HTML_BLOCK_START;
|
|
mode = MODE_HTML;
|
|
}
|
|
else if(LookAhead(input, "[/code]"))
|
|
{
|
|
t->markup.type = CODE_BLOCK_STOP;
|
|
mode = MODE_TEXT;
|
|
}
|
|
else if(LookAhead(input, "[/html]"))
|
|
{
|
|
t->markup.type = HTML_BLOCK_STOP;
|
|
mode = MODE_TEXT;
|
|
}
|
|
else if(LookAhead(input, "[maths]"))
|
|
{
|
|
t->markup.type = MATHS_BLOCK_START;
|
|
mode = MODE_MATHS_BLOCK;
|
|
}
|
|
else if(LookAhead(input, "[/maths]"))
|
|
{
|
|
t->markup.type = MATHS_BLOCK_STOP;
|
|
mode = MODE_TEXT;
|
|
}
|
|
else if(LookAhead(input, "[url="))
|
|
{
|
|
AttributedMarkupToken(input, URL_START, t);
|
|
}
|
|
else if(LookAhead(input, "[/url]"))
|
|
{
|
|
t->markup.type = URL_STOP;
|
|
}
|
|
else if(LookAhead(input, "[img="))
|
|
{
|
|
AttributedMarkupToken(input, IMG, t);
|
|
}
|
|
else
|
|
{
|
|
//TODO(martin): should issue a warning ?
|
|
CharacterToken(input, t);
|
|
}
|
|
}
|
|
|
|
void RepeatableMarkupToken(FILE* input, char m, markup_type type, token* t)
|
|
{
|
|
char c;
|
|
int count = 0;
|
|
while((c = getc(input)) == m)
|
|
{
|
|
count++;
|
|
}
|
|
ungetc(c, input);
|
|
|
|
t->type = MARKUP;
|
|
t->markup.type = type;
|
|
t->markup.value = count;
|
|
}
|
|
|
|
void LessToken(FILE* input, token* t)
|
|
{
|
|
t->html.text[0] = getc(input);
|
|
char c = Peek(input);
|
|
if( c == '!'
|
|
|| (c >= 'A' && c <= 'Z')
|
|
|| (c >= 'a' && c <= 'z')
|
|
|| c == '/')
|
|
{
|
|
bool quotes = false;
|
|
bool dquotes = false;
|
|
int count = 1;
|
|
while(((c = getc(input)) != EOF) && (count < MAX_HTML_TAG_LENGTH))
|
|
{
|
|
t->html.text[count] = c;
|
|
|
|
if(c == '>' && !quotes && !dquotes)
|
|
{
|
|
count++;
|
|
break;
|
|
}
|
|
else if(c == '\'' && !dquotes)
|
|
{
|
|
quotes = !quotes;
|
|
}
|
|
else if(c == '\"' && !quotes)
|
|
{
|
|
dquotes = !dquotes;
|
|
}
|
|
count++;
|
|
}
|
|
if(count >= MAX_HTML_TAG_LENGTH || c == EOF)
|
|
{
|
|
//issue an error
|
|
}
|
|
else
|
|
{
|
|
t->type = HTML_TAG;
|
|
t->html.text[count] = '\0';
|
|
}
|
|
}
|
|
else if(c == '-')
|
|
{
|
|
while(c == '-')
|
|
{
|
|
c = getc(input);
|
|
}
|
|
ungetc(c, input);
|
|
t->type = SYMBOL;
|
|
t->symbol.code = LARR;
|
|
|
|
}
|
|
else
|
|
{
|
|
ungetc(t->html.text[0], input);
|
|
CharacterToken(input, t);
|
|
}
|
|
}
|
|
|
|
void EscapeToken(FILE* input, token* t)
|
|
{
|
|
getc(input);
|
|
t->type = SYMBOL;
|
|
|
|
if(LookAhead(input, "star"))
|
|
{
|
|
t->symbol.code = STAR;
|
|
}
|
|
else if(LookAhead(input, "lowstar"))
|
|
{
|
|
t->symbol.code = LOSTAR;
|
|
}
|
|
else if(LookAhead(input, "minus"))
|
|
{
|
|
SymbolToken(SUBSTRACT, t);
|
|
}
|
|
else if(LookAhead(input, "div"))
|
|
{
|
|
t->symbol.code = DIVIDE;
|
|
}
|
|
else if(LookAhead(input, "cdot"))
|
|
{
|
|
t->symbol.code = CDOT;
|
|
}
|
|
else if(LookAhead(input, "times"))
|
|
{
|
|
t->symbol.code = MULTIPLY;
|
|
}
|
|
else if(LookAhead(input, "otimes"))
|
|
{
|
|
t->symbol.code = OTIMES;
|
|
}
|
|
else if(LookAhead(input, "leq"))
|
|
{
|
|
t->symbol.code = LEQ;
|
|
}
|
|
else if(LookAhead(input, "geq"))
|
|
{
|
|
t->symbol.code = GEQ;
|
|
}
|
|
else if(LookAhead(input, "inf"))
|
|
{
|
|
t->symbol.code = INF;
|
|
}
|
|
else if(LookAhead(input, "larr"))
|
|
{
|
|
t->symbol.code = LARR;
|
|
}
|
|
else if(LookAhead(input, "rarr"))
|
|
{
|
|
t->symbol.code = RARR;
|
|
}
|
|
else if(LookAhead(input, "vec"))
|
|
{
|
|
MarkupCharToken(VECTOR, t);
|
|
}
|
|
else if(LookAhead(input, "sqrt"))
|
|
{
|
|
MarkupCharToken(SQRT, t);
|
|
}
|
|
else if(LookAhead(input, "frac"))
|
|
{
|
|
MarkupCharToken(FRACTION, t);
|
|
}
|
|
else if(LookAhead(input, "nsum"))
|
|
{
|
|
MarkupCharToken(NSUM, t);
|
|
}
|
|
else if(LookAhead(input, "nprod"))
|
|
{
|
|
MarkupCharToken(NPRODUCT, t);
|
|
}
|
|
else if(LookAhead(input, "alpha"))
|
|
{
|
|
t->symbol.code = ALPHA;
|
|
}
|
|
else if(LookAhead(input, "beta"))
|
|
{
|
|
t->symbol.code = BETA;
|
|
}
|
|
else if(LookAhead(input, "gamma"))
|
|
{
|
|
t->symbol.code = GAMMA;
|
|
}
|
|
else if(LookAhead(input, "delta"))
|
|
{
|
|
t->symbol.code = DELTA;
|
|
}
|
|
else if(LookAhead(input, "epsilon"))
|
|
{
|
|
t->symbol.code = EPSILON;
|
|
}
|
|
else if(LookAhead(input, "zeta"))
|
|
{
|
|
t->symbol.code = ZETA;
|
|
}
|
|
else if(LookAhead(input, "eta"))
|
|
{
|
|
t->symbol.code = ETA;
|
|
}
|
|
else if(LookAhead(input, "theta"))
|
|
{
|
|
t->symbol.code = THETA;
|
|
}
|
|
else if(LookAhead(input, "iota"))
|
|
{
|
|
t->symbol.code = IOTA;
|
|
}
|
|
else if(LookAhead(input, "kappa"))
|
|
{
|
|
t->symbol.code = KAPPA;
|
|
}
|
|
else if(LookAhead(input, "lambda"))
|
|
{
|
|
t->symbol.code = LAMBDA;
|
|
}
|
|
else if(LookAhead(input, "mu"))
|
|
{
|
|
t->symbol.code = MU;
|
|
}
|
|
else if(LookAhead(input, "nu"))
|
|
{
|
|
t->symbol.code = NU;
|
|
}
|
|
else if(LookAhead(input, "xi"))
|
|
{
|
|
t->symbol.code = XI;
|
|
}
|
|
else if(LookAhead(input, "omicron"))
|
|
{
|
|
t->symbol.code = OMICRON;
|
|
}
|
|
else if(LookAhead(input, "pi"))
|
|
{
|
|
t->symbol.code = PI;
|
|
}
|
|
else if(LookAhead(input, "rho"))
|
|
{
|
|
t->symbol.code = RHO;
|
|
}
|
|
else if(LookAhead(input, "sigma"))
|
|
{
|
|
t->symbol.code = SIGMA;
|
|
}
|
|
else if(LookAhead(input, "tau"))
|
|
{
|
|
t->symbol.code = TAU;
|
|
}
|
|
else if(LookAhead(input, "upsilon"))
|
|
{
|
|
t->symbol.code = UPSILON;
|
|
}
|
|
else if(LookAhead(input, "phi"))
|
|
{
|
|
t->symbol.code = PHI;
|
|
}
|
|
else if(LookAhead(input, "chi"))
|
|
{
|
|
t->symbol.code = CHI;
|
|
}
|
|
else if(LookAhead(input, "psi"))
|
|
{
|
|
t->symbol.code = PSI;
|
|
}
|
|
else if(LookAhead(input, "omega"))
|
|
{
|
|
t->symbol.code = OMEGA;
|
|
}
|
|
else if(LookAhead(input, "Alpha"))
|
|
{
|
|
t->symbol.code = ALPHA_UPPER;
|
|
}
|
|
else if(LookAhead(input, "Beta"))
|
|
{
|
|
t->symbol.code = BETA_UPPER;
|
|
}
|
|
else if(LookAhead(input, "Gamma"))
|
|
{
|
|
t->symbol.code = GAMMA_UPPER;
|
|
}
|
|
else if(LookAhead(input, "Delta"))
|
|
{
|
|
t->symbol.code = DELTA_UPPER;
|
|
}
|
|
else if(LookAhead(input, "Epsilon"))
|
|
{
|
|
t->symbol.code = EPSILON_UPPER;
|
|
}
|
|
else if(LookAhead(input, "Zeta"))
|
|
{
|
|
t->symbol.code = ZETA_UPPER;
|
|
}
|
|
else if(LookAhead(input, "Eta"))
|
|
{
|
|
t->symbol.code = ETA_UPPER;
|
|
}
|
|
else if(LookAhead(input, "Theta"))
|
|
{
|
|
t->symbol.code = THETA_UPPER;
|
|
}
|
|
else if(LookAhead(input, "Iota"))
|
|
{
|
|
t->symbol.code = IOTA_UPPER;
|
|
}
|
|
else if(LookAhead(input, "Kappa"))
|
|
{
|
|
t->symbol.code = KAPPA_UPPER;
|
|
}
|
|
else if(LookAhead(input, "Lambda"))
|
|
{
|
|
t->symbol.code = LAMBDA_UPPER;
|
|
}
|
|
else if(LookAhead(input, "Mu"))
|
|
{
|
|
t->symbol.code = MU_UPPER;
|
|
}
|
|
else if(LookAhead(input, "Nu"))
|
|
{
|
|
t->symbol.code = NU_UPPER;
|
|
}
|
|
else if(LookAhead(input, "Xi"))
|
|
{
|
|
t->symbol.code = XI_UPPER;
|
|
}
|
|
else if(LookAhead(input, "Omicron"))
|
|
{
|
|
t->symbol.code = OMICRON_UPPER;
|
|
}
|
|
else if(LookAhead(input, "Pi"))
|
|
{
|
|
t->symbol.code = PI_UPPER;
|
|
}
|
|
else if(LookAhead(input, "Rho"))
|
|
{
|
|
t->symbol.code = RHO_UPPER;
|
|
}
|
|
else if(LookAhead(input, "Sigma"))
|
|
{
|
|
t->symbol.code = SIGMA_UPPER;
|
|
}
|
|
else if(LookAhead(input, "Tau"))
|
|
{
|
|
t->symbol.code = TAU_UPPER;
|
|
}
|
|
else if(LookAhead(input, "Upsilon"))
|
|
{
|
|
t->symbol.code = UPSILON_UPPER;
|
|
}
|
|
else if(LookAhead(input, "Phi"))
|
|
{
|
|
t->symbol.code = PHI_UPPER;
|
|
}
|
|
else if(LookAhead(input, "Chi"))
|
|
{
|
|
t->symbol.code = CHI_UPPER;
|
|
}
|
|
else if(LookAhead(input, "Psi"))
|
|
{
|
|
t->symbol.code = PSI_UPPER;
|
|
}
|
|
else if(LookAhead(input, "Omega"))
|
|
{
|
|
t->symbol.code = OMEGA_UPPER;
|
|
}
|
|
else if(LookAhead(input, "thin"))
|
|
{
|
|
t->symbol.code = THINSPACE;
|
|
}
|
|
else if(LookAhead(input, "b"))
|
|
{
|
|
MarkupCharToken(BOLD, t);
|
|
}
|
|
else if(LookAhead(input, "i"))
|
|
{
|
|
MarkupCharToken(ITALIC, t);
|
|
}
|
|
else if(LookAhead(input, "u"))
|
|
{
|
|
MarkupCharToken(UNDERLINE, t);
|
|
}
|
|
else if(LookAhead(input, "r"))
|
|
{
|
|
MarkupCharToken(REGULAR, t);
|
|
}
|
|
else
|
|
{
|
|
t->type = ESC;
|
|
t->c = getc(input);
|
|
}
|
|
}
|
|
|
|
void GetNextTokenInHTMLMode(FILE* input, token* t)
|
|
{
|
|
char c = Peek(input);
|
|
if(c==EOF)
|
|
{
|
|
t->type = ENDF;
|
|
return;
|
|
}
|
|
if(c == '[')
|
|
{
|
|
t->type = MARKUP;
|
|
if(LookAhead(input, "[/html]"))
|
|
{
|
|
t->markup.type = CODE_INLINE_STOP;
|
|
mode = MODE_TEXT;
|
|
}
|
|
else
|
|
{
|
|
CharacterToken(input, t);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CharacterToken(input, t);
|
|
}
|
|
}
|
|
|
|
void GetNextTokenInCodeMode(FILE* input, token* t)
|
|
{
|
|
char c = Peek(input);
|
|
if(c==EOF)
|
|
{
|
|
t->type = ENDF;
|
|
return;
|
|
}
|
|
if(c == '[')
|
|
{
|
|
t->type = MARKUP;
|
|
if(LookAhead(input, "[/c]"))
|
|
{
|
|
t->markup.type = CODE_INLINE_STOP;
|
|
mode = MODE_TEXT;
|
|
}
|
|
else if(LookAhead(input, "[/code]"))
|
|
{
|
|
t->markup.type = CODE_BLOCK_STOP;
|
|
mode = MODE_TEXT;
|
|
}
|
|
else
|
|
{
|
|
CharacterToken(input, t);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CharacterToken(input, t);
|
|
}
|
|
}
|
|
|
|
void GetNextTokenInMathsMode(FILE* input, token* t)
|
|
{
|
|
char c = Peek(input);
|
|
if(c==EOF)
|
|
{
|
|
t->type = ENDF;
|
|
return;
|
|
}
|
|
switch(c)
|
|
{
|
|
case ':':
|
|
getc(input);
|
|
MarkupCharToken(BOLD, t);
|
|
break;
|
|
case '*':
|
|
getc(input);
|
|
SymbolToken(MULTIPLY, t);
|
|
break;
|
|
case '-':
|
|
getc(input);
|
|
SymbolToken(SUBSTRACT, t);
|
|
break;
|
|
case '_':
|
|
getc(input);
|
|
MarkupCharToken(SUBSCRIPT, t);
|
|
break;
|
|
case '^':
|
|
getc(input);
|
|
MarkupCharToken(SUPERSCRIPT, t);
|
|
break;
|
|
case '\n':
|
|
EndlToken(input, t);
|
|
break;
|
|
case '[':
|
|
BlockToken(input, t);
|
|
break;
|
|
case '<':
|
|
getc(input);
|
|
c = Peek(input);
|
|
if(c == '=')
|
|
{
|
|
getc(input);
|
|
SymbolToken(LEQ, t);
|
|
}
|
|
else
|
|
{
|
|
ungetc('<', input);
|
|
LessToken(input, t);
|
|
}
|
|
break;
|
|
case '>':
|
|
getc(input);
|
|
c = Peek(input);
|
|
if(c == '=')
|
|
{
|
|
getc(input);
|
|
SymbolToken(GEQ, t);
|
|
}
|
|
else
|
|
{
|
|
ungetc('>', input);
|
|
CharacterToken(input, t);
|
|
}
|
|
break;
|
|
case '\\':
|
|
EscapeToken(input, t);
|
|
break;
|
|
default:
|
|
CharacterToken(input, t);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void RepeatableHyphen(FILE* input, token* t)
|
|
{
|
|
char c;
|
|
int count = 1;
|
|
while((c = getc(input)) == '-')
|
|
{
|
|
count++;
|
|
}
|
|
|
|
t->type = SYMBOL;
|
|
if(c == '>')
|
|
{
|
|
t->symbol.code = RARR;
|
|
}
|
|
else
|
|
{
|
|
if(count <= 3)
|
|
{
|
|
t->symbol.code = EMDASH;
|
|
}
|
|
else
|
|
{
|
|
t->symbol.code = LINE;
|
|
}
|
|
ungetc(c, input);
|
|
}
|
|
}
|
|
|
|
void LookAheadForList(FILE* input, token* t)
|
|
{
|
|
char buffer[8];
|
|
bool plain = false;
|
|
int count = 0;
|
|
while(count < 8)
|
|
{
|
|
char c = getc(input);
|
|
buffer[count] = c;
|
|
count++;
|
|
|
|
if(c == '-')
|
|
{
|
|
if(LookAhead(input, " "))
|
|
{
|
|
t->type = MARKUP;
|
|
t->markup.type = LIST;
|
|
t->markup.value = count;
|
|
return;
|
|
}
|
|
else if(count==1 && LookAhead(input, "-"))
|
|
{
|
|
RepeatableHyphen(input, t);
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
else if(c != '\t')
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
for(int i=count-1;i>0;i--)
|
|
{
|
|
ungetc(buffer[i], input);
|
|
}
|
|
t->type = CHAR;
|
|
t->c = buffer[0];
|
|
}
|
|
|
|
void GetNextTokenInTextMode(FILE* input, token* t)
|
|
{
|
|
char c = Peek(input);
|
|
if(c==EOF)
|
|
{
|
|
t->type = ENDF;
|
|
return;
|
|
}
|
|
switch(c)
|
|
{
|
|
case '=':
|
|
RepeatableMarkupToken(input, '=', SECTION, t);
|
|
break;
|
|
case '\t': case '-':
|
|
LookAheadForList(input, t);
|
|
break;
|
|
case '_':
|
|
getc(input);
|
|
MarkupCharToken(UNDERLINE, t);
|
|
break;
|
|
case '*':
|
|
getc(input);
|
|
MarkupCharToken(BOLD, t);
|
|
break;
|
|
case '/':
|
|
getc(input);
|
|
MarkupCharToken(ITALIC, t);
|
|
break;
|
|
case '\n':
|
|
EndlToken(input, t);
|
|
break;
|
|
case '[':
|
|
BlockToken(input, t);
|
|
break;
|
|
case '<':
|
|
LessToken(input, t);
|
|
break;
|
|
case '\\':
|
|
return EscapeToken(input, t);
|
|
default:
|
|
CharacterToken(input, t);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void GetNextToken(FILE* input, token* t)
|
|
{
|
|
//NOTE(martin): finds the next token from input, effectively consumming characters
|
|
// if no token is found, those 'lookahead' characters are pushed back to the stream
|
|
|
|
switch(mode)
|
|
{
|
|
case MODE_HTML:
|
|
return(GetNextTokenInHTMLMode(input, t));
|
|
|
|
case MODE_CODE_INLINE: case MODE_CODE_BLOCK:
|
|
return(GetNextTokenInCodeMode(input, t));
|
|
|
|
case MODE_MATHS_INLINE: case MODE_MATHS_BLOCK:
|
|
return(GetNextTokenInMathsMode(input, t));
|
|
|
|
case MODE_TEXT: default:
|
|
GetNextTokenInTextMode(input, t);
|
|
}
|
|
}
|
|
|
|
void ResetScanMode()
|
|
{
|
|
mode = MODE_TEXT;
|
|
}
|
|
|