/* * Lexer for .aux files * * This file is part of Beastie * SPDX-FileCopyrightText: 2023 Norman Gray * SPDX-License-Identifier: BSD-2-Clause */ %top{ #if __GNUC__ // for fileno #define _XOPEN_SOURCE 600 #endif } %{ #include #include "beastie.h" #include "util.h" #include "parse-aux.h" #include "parse-aux.tab.h" #ifndef WITH_MAIN #define WITH_MAIN 0 #endif %} %option prefix="aux" reentrant noyywrap nounput yylineno bison-bridge bison-locations %option extra-type="aux_extra_t" ALPHABETIC [a-zA-Z@] STRINGCONTENTS [^%\\{} \t\n][^%\\{}]* DIGIT [0-9] OWS [[:space:]]* WS [[:space:]]+ %% {OWS}"\\"{ALPHABETIC}+{OWS} { char *p = yytext; while (isspace(*p)) p++; char* start = p+1; while (*p != '\0' && !isspace(*p)) p++; *yylval = s7_make_string_with_length(S7, start, p-start); return CMD; } "{" { *yylval = scan_to_matching_char(&input, yyscanner, yyget_lineno(yyscanner), NULL, '}', 0); return BRACEDSTRING; } "%".* return WHITESPACE; {STRINGCONTENTS}+ { *yylval = s7_make_string(S7, yytext); return STRING; } {WS} return WHITESPACE; . { fprintf(stderr, "Unexpected character '%c' at line %d of .aux\n", yytext[0], yyget_lineno(yyscanner)); } %% yyscan_t parse_aux_setup_file(aux_extra_t extra, FILE* f) { yyscan_t scanner; yylex_init_extra(extra, &scanner); extra->yyscanbuf = 0; if (f != NULL) { yyset_in(f, scanner); } return scanner; } yyscan_t parse_aux_setup_string(aux_extra_t extra, const char* s) { yyscan_t scanner; yylex_init_extra(extra, &scanner); extra->yyscanbuf = (void*)yy_scan_string(s, scanner); yyset_lineno(1, scanner); return scanner; } void parse_aux_finish(aux_extra_t extra, yyscan_t scanner) { if (extra->yyscanbuf) { yy_delete_buffer((YY_BUFFER_STATE)extra->yyscanbuf, scanner); extra->yyscanbuf = NULL; } yylex_destroy(scanner); } #if WITH_MAIN #include #include #include "util.h" s7_scheme* S7; static void display_lexemes(yyscan_t scanner) { int l; YYSTYPE one_value; YYLTYPE locp; while ((l = auxlex(&one_value, &locp, scanner)) != 0) { switch (l) { case CMD: s7w("command: ", one_value, "\n"); break; case STRING: s7w("string:<", one_value, ">\n"); break; case BRACEDSTRING: s7w("bracedstring:<", one_value, ">\n"); break; case WHITESPACE: printf("WHITESPACE\n"); break; default: printf("Unexpected lexeme: %d\n", l); } } } const char* progname; void Usage(void) { fprintf(stderr, "Usage: %s [foo.aux]\n", progname); exit(1); } int main(int argc, char** argv) { const char* infilename; progname = argv[0]; if (argc > 0) { switch (argc) { case 1: infilename = NULL; break; case 2: if (argv[1][0] == '-') Usage(); infilename = argv[1]; break; default: Usage(); } } S7 = s7_init(); FILE* in; if (infilename) { in = fopen(argv[1], "r"); if (in == NULL) { fprintf(stderr, "Can't open file %s to read\n", infilename); exit(1); } } else { in = stdin; } struct aux_extra_s S; yyscan_t scanner = parse_aux_setup_file(&S, in); display_lexemes(scanner); parse_aux_finish(&S, scanner); fclose(in); } #endif