mojoshader_lexer.re
changeset 555 940821555fda
child 564 c669568326fb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mojoshader_lexer.re	Mon Feb 09 17:53:54 2009 -0500
@@ -0,0 +1,174 @@
+/**
+ * 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_preprocessor.c from the .re file with re2c...
+// re2c -is -o mojoshader_lexer_preprocessor.c mojoshader_lexer_preprocessor.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;
+
+#define RET(t) { update_state(s, cursor, token); return t; }
+#define YYCTYPE uchar
+#define YYCURSOR cursor
+#define YYLIMIT limit
+#define YYMARKER s->lexer_marker
+#define YYFILL(n) { if ((n) == 1) { RET(TOKEN_EOI); } }
+
+static void update_state(IncludeState *s, const uchar *cur, const uchar *tok)
+{
+    s->bytes_left -= (unsigned int) (cur - ((const uchar *) s->source));
+    s->source = (const char *) cur;
+    s->token = (const char *) tok;
+} // update_state
+
+Token preprocessor_internal_lexer(IncludeState *s)
+{
+    const uchar *cursor = (const uchar *) s->source;
+    const uchar *token;
+    const uchar *limit = cursor + s->bytes_left;
+
+scanner_loop:
+    token = cursor;
+
+    if (YYLIMIT == YYCURSOR)
+        RET(TOKEN_EOI);
+
+/*!re2c
+    any = [\000-\377];
+    O = [0-7];
+    D = [0-9];
+    L = [a-zA-Z_];
+    H = [a-fA-F0-9];
+    E = [Ee] [+-]? D+;
+    FS = [fFlL];
+    IS = [uUlL]*;
+    ESC = [\\] ([abfnrtv?'"\\] | "x" H+ | O+);
+    PP = "#" [ \t]*;
+    NEWLINE = "\r\n" | "\r" | "\n";
+    WHITESPACE = [ \t\v\f]+;
+*/
+
+/*!re2c
+    "/*"            { goto multilinecomment; }
+    "//"            { goto singlelinecomment; }
+
+    L (L|D)*        { RET(TOKEN_IDENTIFIER); }
+    
+    ("0" [xX] H+ IS?) | ("0" D+ IS?) | (D+ IS?) |
+    (['] (ESC|any\[\n\\'])* ['])
+                    { RET(TOKEN_INT_LITERAL); }
+    
+    (D+ E FS?) | (D* "." D+ E? FS?) | (D+ "." D* E? FS?)
+                    { RET(TOKEN_FLOAT_LITERAL); }
+    
+    (["] (ESC|any\[\n\\"])* ["])
+                    { RET(TOKEN_STRING_LITERAL); }
+    
+    "..."           { RET(TOKEN_ELLIPSIS); }
+    ">>"            { 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_HASHHASH); }
+    "("             { RET('('); }
+    ")"             { RET(')'); }
+    "["             { RET('['); }
+    "]"             { RET(']'); }
+    "."             { RET('.'); }
+    ","             { RET(','); }
+    "&"             { RET('&'); }
+    "!"             { RET('!'); }
+    "~"             { RET('~'); }
+    "-"             { RET('-'); }
+    "+"             { RET('+'); }
+    "*"             { RET('*'); }
+    "/"             { RET('/'); }
+    "%"             { RET('%'); }
+    "<"             { RET('<'); }
+    ">"             { RET('>'); }
+    "^"             { RET('^'); }
+    "|"             { RET('|'); }
+    ":"             { RET(':'); }
+    ";"             { RET(';'); }
+    "{"             { RET('{'); }
+    "}"             { RET('}'); }
+    "="             { RET('='); }
+    "?"             { RET('?'); }
+    "\\"            { RET('\\'); }
+    "#"             { RET('#'); }
+
+    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); }
+
+    WHITESPACE      { goto scanner_loop; }
+    NEWLINE         { s->line++; goto scanner_loop; }
+    any             { printf("bad char\n"); goto scanner_loop; }
+*/
+
+multilinecomment:
+    if (YYLIMIT == YYCURSOR)
+        RET(TOKEN_PP_INCOMPLETE_COMMENT);
+// The "*\/" is just to avoid screwing up text editor syntax highlighting.
+/*!re2c
+    "*\/"           { goto scanner_loop; }
+    NEWLINE         { s->line++; goto multilinecomment; }
+    any             { goto multilinecomment; }
+*/
+
+singlelinecomment:
+    if (YYLIMIT == YYCURSOR)
+        RET(TOKEN_EOI);
+/*!re2c
+    NEWLINE         { s->line++; goto scanner_loop; }
+    any             { goto singlelinecomment; }
+*/
+
+// !!! FIXME
+/*
+bad_chars:
+    if (YYLIMIT == YYCURSOR)
+        RET(TOKEN_BAD_TOKEN);
+*/
+
+/*!re2c
+    NEWLINE         { s->line++; goto scanner_loop; }
+    WHITESPACE      { goto scanner_loop; }
+    any             { goto singlelinecomment; }
+*/
+
+    assert(0 && "Shouldn't hit this code");
+    RET(TOKEN_UNKNOWN);
+} // preprocessor_internal_lexer
+
+// end of mojoshader_lexer_preprocessor.re (or .c) ...
+