Show More
Commit Description:
Various UI improvements.
Commit Description:
Various UI improvements.
References:
File last commit:
Show/Diff file:
Action:
FNA/lib/MojoShader/mojoshader_lexer.re
276 lines | 9.1 KiB | text/plain | TextLexer
276 lines | 9.1 KiB | text/plain | TextLexer
r0 | /** | |||
* MojoShader; generate shader programs from bytecode of compiled | ||||
* Direct3D shaders. | ||||
* | ||||
* Please see the file LICENSE.txt in the source's root directory. | ||||
* | ||||
* This file written by Ryan C. Gordon. | ||||
*/ | ||||
// This was originally based on examples/pp-c.re from re2c: http://re2c.org/ | ||||
// re2c is public domain code. | ||||
// | ||||
// You build mojoshader_lexer.c from the .re file with re2c... | ||||
// re2c -is -o mojoshader_lexer.c mojoshader_lexer.re | ||||
// | ||||
// Changes to the lexer are done to the .re file, not the C code! | ||||
// | ||||
// Please note that this isn't a perfect C lexer, since it is used for both | ||||
// HLSL and shader assembly language, and follows the quirks of Microsoft's | ||||
// tools. | ||||
#define __MOJOSHADER_INTERNAL__ 1 | ||||
#include "mojoshader_internal.h" | ||||
typedef unsigned char uchar; | ||||
/*!max:re2c */ | ||||
#define RET(t) return update_state(s, eoi, cursor, token, (Token) t) | ||||
#define YYCTYPE uchar | ||||
#define YYCURSOR cursor | ||||
#define YYLIMIT limit | ||||
#define YYMARKER s->lexer_marker | ||||
#define YYFILL(n) { if ((n) == 1) { cursor = sentinel; limit = cursor + YYMAXFILL; eoi = 1; } } | ||||
static uchar sentinel[YYMAXFILL]; | ||||
static Token update_state(IncludeState *s, int eoi, const uchar *cur, | ||||
const uchar *tok, const Token val) | ||||
{ | ||||
if (eoi) | ||||
{ | ||||
s->bytes_left = 0; | ||||
s->source = (const char *) s->source_base + s->orig_length; | ||||
if ( (tok >= sentinel) && (tok < (sentinel+YYMAXFILL)) ) | ||||
s->token = s->source; | ||||
else | ||||
s->token = (const char *) tok; | ||||
} // if | ||||
else | ||||
{ | ||||
s->bytes_left -= (unsigned int) (cur - ((const uchar *) s->source)); | ||||
s->source = (const char *) cur; | ||||
s->token = (const char *) tok; | ||||
} // else | ||||
s->tokenlen = (unsigned int) (s->source - s->token); | ||||
s->tokenval = val; | ||||
return val; | ||||
} // update_state | ||||
Token preprocessor_lexer(IncludeState *s) | ||||
{ | ||||
const uchar *cursor = (const uchar *) s->source; | ||||
const uchar *token = cursor; | ||||
const uchar *matchptr; | ||||
const uchar *limit = cursor + s->bytes_left; | ||||
int eoi = 0; | ||||
/*!re2c | ||||
ANY = [\000-\377]; | ||||
ANYLEGAL = [a-zA-Z0-9_/'*=+%^&|!#<>()[{}.,~^:;? \t\v\f\r\n\-\]\\]; | ||||
O = [0-7]; | ||||
D = [0-9]; | ||||
L = [a-zA-Z_]; | ||||
H = [a-fA-F0-9]; | ||||
E = [Ee] [+-]? D+; | ||||
FS = [fFhH]; | ||||
IS = [uUlL]*; | ||||
ESC = [\\] ([abfnrtv?'"\\] | "x" H+ | O+); | ||||
PP = "#" [ \t]*; | ||||
NEWLINE = ("\r\n" | "\r" | "\n"); | ||||
WHITESPACE = [ \t\v\f]+; | ||||
*/ | ||||
// preprocessor directives are only valid at start of line. | ||||
if (s->tokenval == ((Token) '\n')) | ||||
goto ppdirective; // may jump back to scanner_loop. | ||||
scanner_loop: | ||||
if (YYLIMIT == YYCURSOR) YYFILL(1); | ||||
token = cursor; | ||||
/*!re2c | ||||
"\\" [ \t\v\f]* NEWLINE { s->line++; goto scanner_loop; } | ||||
"/*" { goto multilinecomment; } | ||||
"//" { goto singlelinecomment; } | ||||
L (L|D)* { RET(TOKEN_IDENTIFIER); } | ||||
("0" [xX] H+ IS?) | ("0" D+ IS?) | (D+ IS?) | | ||||
(['] (ESC|ANY\[\r\n\\'])* [']) | ||||
{ RET(TOKEN_INT_LITERAL); } | ||||
(D+ E FS?) | (D* "." D+ E? FS?) | (D+ "." D* E? FS?) | ||||
{ RET(TOKEN_FLOAT_LITERAL); } | ||||
(["] (ESC|ANY\[\r\n\\"])* ["]) | ||||
{ RET(TOKEN_STRING_LITERAL); } | ||||
">>=" { RET(TOKEN_RSHIFTASSIGN); } | ||||
"<<=" { RET(TOKEN_LSHIFTASSIGN); } | ||||
"+=" { RET(TOKEN_ADDASSIGN); } | ||||
"-=" { RET(TOKEN_SUBASSIGN); } | ||||
"*=" { RET(TOKEN_MULTASSIGN); } | ||||
"/=" { RET(TOKEN_DIVASSIGN); } | ||||
"%=" { RET(TOKEN_MODASSIGN); } | ||||
"^=" { RET(TOKEN_XORASSIGN); } | ||||
"&=" { RET(TOKEN_ANDASSIGN); } | ||||
"|=" { RET(TOKEN_ORASSIGN); } | ||||
"++" { RET(TOKEN_INCREMENT); } | ||||
"--" { RET(TOKEN_DECREMENT); } | ||||
">>" { RET(TOKEN_RSHIFT); } | ||||
"<<" { RET(TOKEN_LSHIFT); } | ||||
"&&" { RET(TOKEN_ANDAND); } | ||||
"||" { RET(TOKEN_OROR); } | ||||
"<=" { RET(TOKEN_LEQ); } | ||||
">=" { RET(TOKEN_GEQ); } | ||||
"==" { RET(TOKEN_EQL); } | ||||
"!=" { RET(TOKEN_NEQ); } | ||||
"#" { RET(TOKEN_HASH); } | ||||
"##" { RET(TOKEN_HASHHASH); } | ||||
"(" { RET('('); } | ||||
")" { RET(')'); } | ||||
"[" { RET('['); } | ||||
"]" { RET(']'); } | ||||
"." { RET('.'); } | ||||
"," { RET(','); } | ||||
"&" { RET('&'); } | ||||
"!" { RET('!'); } | ||||
"~" { RET('~'); } | ||||
"-" { RET('-'); } | ||||
"+" { RET('+'); } | ||||
"*" { RET('*'); } | ||||
"/" { RET('/'); } | ||||
"%" { RET('%'); } | ||||
"<" { RET('<'); } | ||||
">" { RET('>'); } | ||||
"^" { RET('^'); } | ||||
"|" { RET('|'); } | ||||
":" { RET(':'); } | ||||
"{" { RET('{'); } | ||||
"}" { RET('}'); } | ||||
"=" { RET('='); } | ||||
"?" { RET('?'); } | ||||
";" { if (s->asm_comments) goto singlelinecomment; RET(';'); } | ||||
"\000" { if (eoi) { RET(TOKEN_EOI); } goto bad_chars; } | ||||
WHITESPACE { if (s->report_whitespace) RET(' '); goto scanner_loop; } | ||||
NEWLINE { s->line++; RET('\n'); } | ||||
ANY { goto bad_chars; } | ||||
*/ | ||||
multilinecomment: | ||||
if (YYLIMIT == YYCURSOR) YYFILL(1); | ||||
matchptr = cursor; | ||||
// The "*\/" is just to avoid screwing up text editor syntax highlighting. | ||||
/*!re2c | ||||
"*\/" { | ||||
if (s->report_comments) | ||||
RET(TOKEN_MULTI_COMMENT); | ||||
else if (s->report_whitespace) | ||||
RET(' '); | ||||
// Microsoft's preprocessor allows multiline comments | ||||
// before a preprocessor directive, even though C/C++ | ||||
// doesn't. See if we've hit this case. | ||||
#if MATCH_MICROSOFT_PREPROCESSOR | ||||
if (s->tokenval == ((Token) '\n')) // was start of line? | ||||
{ | ||||
update_state(s, eoi, cursor, token, (Token) '\n'); | ||||
goto ppdirective; // may jump back to scanner_loop. | ||||
} | ||||
#endif | ||||
goto scanner_loop; | ||||
} | ||||
NEWLINE { | ||||
s->line++; | ||||
goto multilinecomment; | ||||
} | ||||
"\000" { | ||||
if (eoi) | ||||
RET(TOKEN_INCOMPLETE_COMMENT); | ||||
goto multilinecomment; | ||||
} | ||||
ANY { goto multilinecomment; } | ||||
*/ | ||||
singlelinecomment: | ||||
if (YYLIMIT == YYCURSOR) YYFILL(1); | ||||
matchptr = cursor; | ||||
/*!re2c | ||||
NEWLINE { | ||||
s->line++; | ||||
if (s->report_comments) | ||||
{ | ||||
cursor = matchptr; // so we RET('\n') next. | ||||
RET(TOKEN_SINGLE_COMMENT); | ||||
} | ||||
token = matchptr; | ||||
RET('\n'); | ||||
} | ||||
"\000" { | ||||
if (eoi) | ||||
{ | ||||
if (s->report_comments) | ||||
RET(TOKEN_SINGLE_COMMENT); | ||||
else | ||||
RET(TOKEN_EOI); | ||||
} | ||||
goto singlelinecomment; | ||||
} | ||||
ANY { goto singlelinecomment; } | ||||
*/ | ||||
ppdirective: | ||||
if (YYLIMIT == YYCURSOR) YYFILL(1); | ||||
/*!re2c | ||||
PP "include" { RET(TOKEN_PP_INCLUDE); } | ||||
PP "line" { RET(TOKEN_PP_LINE); } | ||||
PP "define" { RET(TOKEN_PP_DEFINE); } | ||||
PP "undef" { RET(TOKEN_PP_UNDEF); } | ||||
PP "if" { RET(TOKEN_PP_IF); } | ||||
PP "ifdef" { RET(TOKEN_PP_IFDEF); } | ||||
PP "ifndef" { RET(TOKEN_PP_IFNDEF); } | ||||
PP "else" { RET(TOKEN_PP_ELSE); } | ||||
PP "elif" { RET(TOKEN_PP_ELIF); } | ||||
PP "endif" { RET(TOKEN_PP_ENDIF); } | ||||
PP "error" { RET(TOKEN_PP_ERROR); } | ||||
PP "pragma" { RET(TOKEN_PP_PRAGMA); } | ||||
WHITESPACE { goto ppdirective; } | ||||
ANY { | ||||
token = cursor = (const uchar *) s->source; | ||||
limit = cursor + s->bytes_left; | ||||
goto scanner_loop; | ||||
} | ||||
*/ | ||||
bad_chars: | ||||
if (YYLIMIT == YYCURSOR) YYFILL(1); | ||||
/*!re2c | ||||
ANYLEGAL { cursor--; RET(TOKEN_BAD_CHARS); } | ||||
"\000" { | ||||
if (eoi) | ||||
{ | ||||
assert( !((token >= sentinel) && | ||||
(token < sentinel+YYMAXFILL)) ); | ||||
eoi = 0; | ||||
cursor = (uchar *) s->source_base + s->orig_length; | ||||
RET(TOKEN_BAD_CHARS); // next call will be EOI. | ||||
} | ||||
goto bad_chars; | ||||
} | ||||
ANY { goto bad_chars; } | ||||
*/ | ||||
assert(0 && "Shouldn't hit this code"); | ||||
RET(TOKEN_UNKNOWN); | ||||
} // preprocessor_lexer | ||||
// end of mojoshader_lexer.re (or .c) ... | ||||