X-Git-Url: https://www.kengrimes.com/gitweb/?p=henge%2Fapc.git;a=blobdiff_plain;f=src%2Flexer.rl;h=5e2fb774e23764188d7556a29f7483739e78de91;hp=36a72abf747f0a47de3cc5e999e26734ae824d96;hb=78ec1b2aecefbd7f6839f54c52b2dd6e3f80bf1a;hpb=6a37e5819abe57422b43d1b356f97e3191ab8850 diff --git a/src/lexer.rl b/src/lexer.rl index 36a72ab..5e2fb77 100644 --- a/src/lexer.rl +++ b/src/lexer.rl @@ -10,83 +10,94 @@ extern //lexer.c void lexer_pushtok(int, YYSTYPE); /* Public */ int lexer_setdirection(uint8_t*, int); +int lexer_lexfile(uint8_t*); +int lexer_lexdir(uint8_t*); int lexer_lexstring(uint8_t*, int); int lexer_setstr(uint8_t*, int); +//apc.c +extern +yypstate* apc_pstate; +extern +yycstate* apc_cstate; +static +YYSTYPE lval_stack[1024], * lvalsp; +#define PUSHTOK(T,L) yypush_parse(apc_pstate, T, (L), apc_cstate) +#define LEXTOK(T,Y,L) do { \ + lvalsp->Y = L; \ + PUSHTOK(T,lvalsp); \ + lvalsp++; \ + ntok++; \ + } while (0); +#define PUSHFACE(F) LEXTOK(FACING, face, F) +#define PUSHREF(R) LEXTOK(REF, ref, R) +#define PUSHLINK() LEXTOK(LINK, val, 0) +#define PUSHNUM(N) LEXTOK(NUM, val, N) +#define PUSHNAME(N) LEXTOK(NAME, str, N) +#define PUSHOP(O) LEXTOK(O, val, 0) +#define PUSHPATH(P) LEXTOK(PATH, str, P) + +/* Lexstring is the main lexer for APC and is generated by ragel. It lexes file names of files + that have been scanned and pushes their types and values into the tok_stack, which yyparse + eventually calls during parsing. */ %%{ machine lexstring; # set up yylval and tok_t to be pushed to stack - action push_ref { te = NULL; errno = 0; - yylval.ref = strtoll((char*)ts,(char**)&te,16); - if (errno | (te != NULL)) + action push_ref { errno = 0; + lval.ref = strtoll((char*)ts,NULL,16); + if (errno) { fprintf(stderr, "Invalid hex number in file %s\n",(char*)str); - if (te != NULL) - { while (str++ < te) - fputc(' ', stderr); - fputc('^', stderr); - } exit(1); } - lexer_pushtok(REF, yylval); ntok++; + PUSHREF(lval.ref); } - action push_link { lexer_pushtok(LINK,(YYSTYPE)0); ntok++; } - action push_val { te = NULL; errno = 0; - yylval.val = strtoll((char*)ts,(char**)&te,10); + action push_link { PUSHLINK(); } + action push_val { errno = 0; + lval.val = strtoll((char*)ts,NULL,10); if (errno) { fprintf(stderr, "strtoll could not parse %s\n", (char*)str); exit(1); } - lexer_pushtok(NUM, yylval); + PUSHNUM(lval.val); } action push_name { printf("Lexer_lexstring:: action:push_name: from %s to %s\n", ts, p); - lexer_pushtok(NAME, yylval); - ntok++; + PUSHNAME(ts); } action push_map { printf("Lexer_lexstring:: action:push_map: pushing map token\n"); - yylval.str = (uint8_t*) '~'; - lexer_pushtok(MOPEN, yylval); - ntok++; + PUSHOP(MAP); } action set_ts { printf("Lexer_lexstring:: action:set_ts. ts = %s\n", p); ts = p; } action push_SS { printf("Lexer_lexstring:: action:push_SS. p = %s\n",p); - yylval.str = (uint8_t*) "SS"; - lexer_pushtok(SS, yylval); - ntok++; + PUSHOP(SS); } action push_S { printf("Lexer_lexstring:: action:push_S. p = %s\n", p); - yylval.val = 0; - lexer_pushtok(D, yylval); + PUSHFACE(SFACE); } action push_SW { printf("Lexer_lexstring:: action:push_SW. p = %s\n", p); - yylval.val = 1; - lexer_pushtok(D, yylval); - } + PUSHFACE(SWFACE); + } action push_W { printf("Lexer_lexstring:: action:push_W. p = %s\n", p); - yylval.val = 2; - lexer_pushtok(D, yylval); + PUSHFACE(WFACE); } action push_NW { printf("Lexer_lexstring:: action:push_NW. p = %s\n", p); - yylval.val = 3; - lexer_pushtok(D, yylval); + PUSHFACE(NWFACE); } action push_N { printf("Lexer_lexstring:: action:push_N. p = %s\n", p); - yylval.val = 4; - lexer_pushtok(D, yylval); + PUSHFACE(NFACE); } action push_NE { printf("Lexer_lexstring:: action:push_NE. p = %s\n", p); - yylval.val = 5; - lexer_pushtok(D, yylval); + PUSHFACE(NEFACE); } action push_E { printf("Lexer_lexstring:: action:push_N. p = %s\n", p); - yylval.val = 6; - lexer_pushtok(D, yylval); + PUSHFACE(EFACE); } action push_SE { printf("Lexer_lexstring:: action:push_N. p = %s\n", p); - yylval.val = 7; - lexer_pushtok(D, yylval); + PUSHFACE(SEFACE); + } + action ref_error { printf("ref from %s to %s has an inappropriate amount of hex digits, it must have eight.\n", ts, p); + exit(1); } - #action lex_error { printf("input error: character %c in filename %s is invalid\n p = %s\n", fc, str, p);} action p { printf("Lexer_lexstring:: p = %s\n", p);} N = 'N' %push_N; @@ -98,23 +109,20 @@ int lexer_setstr(uint8_t*, int); SW = 'SW' %push_SW; SE = 'SE' %push_SE; - #what goes in between tokens in a filename tok_delimiter = [_]; - #types of tokes a filename can contain direction = (N | W | S | E | NW | NE | SW | SE) ; - #make sure 0x123123 doesnt get mistaken for a ref dimensions = (digit+ - '0') >set_ts %push_val 'x' (digit+ - '0') >set_ts %push_val; link = '#' %push_link; SS = ('+SS' %to(push_SS)) | ('+SS' %to(push_SS) link ) ; - ref = '0x' >set_ts alnum+ %push_ref; + ref = '0x' >set_ts alnum{8} $err(ref_error) %push_ref ; val = digit+ >set_ts %push_val ; - name = (lower+ >set_ts) %push_name ; + name = lower >set_ts (lower | digit)* %push_name ; map = '+MAP' %to(push_map); tok = (name | val | ref | dimensions | map | link | SS | direction); - main := (tok tok_delimiter)+ tok [\0]; + main := (tok tok_delimiter)* tok [\0]; write data nofinal noerror noprefix; @@ -125,12 +133,14 @@ int lexer_lexstring int size ) { uint8_t *p; - uint8_t *ts, *pe, *te; - int cs, ntok;//, tok_t; + uint8_t *ts, *pe, *eof; + int cs, ntok; + YYSTYPE lval; + lvalsp = lval_stack; ntok = 0; p = ts = str; - pe = p + size + 1; + pe = eof = p + size + 1; printf("|---Begin lexstring on p = %s, pe = %s.\n",p, pe); @@ -142,6 +152,57 @@ int lexer_lexstring return ntok; } +/* Lexical analysis of a file + Strips a filename to its base name, then sends it to lexer_lexstring before + pushing a PATH token with the filename + Returns the number of tokens pushed to the parser. +*/ +int lexer_lexfile +( uint8_t* filename ) +{ uint8_t* last_period,* iter,* filename_end; + int ntok; + last_period = NULL; + for (iter = filename; *iter; iter++) + switch (*iter) + { // Keep track of the last 'dot' in the name + case '.' : last_period = iter; continue; + // replace '_' with '\0' so bison can use strlen on them as tokens. + case '_' : *iter = '\0'; + default: continue; + } + // Mark the end of the filename + filename_end = iter; + // Lex from either the last period, if present, or filename end + ntok = (last_period) ? + lexer_lexstring(filename, (int)(last_period - filename)) + : lexer_lexstring(filename, (int)(iter - filename)); + // Replace nulls with their original '_' + for (iter = filename; iter < filename_end; iter++) + if (*iter == '\0') + *iter = '_'; + PUSHPATH(filename); + return ntok + 1; + return en_main == 1; +} + +int lexer_lexdir +( uint8_t* dirname ) +{ uint8_t* de = dirname; + int ntok; + ntok = 0; + de = dirname; + if (*de) while (*++de); + ntok = lexer_lexstring(dirname, (int)(de - dirname)); + PUSHOP(CLOPEN); + return ntok; +} + +int lexer_closedir +( void ) +{ int ntok = 0; + PUSHOP(CLCLOSE); + return ntok; +} /**************************/ /****Abandon All Hope******/