From 9b3add5bebc553f9bc1a10a9a6a489135f2a9d4d Mon Sep 17 00:00:00 2001 From: Robert Anisko Date: Sun, 30 Dec 2001 15:01:06 +0000 Subject: [PATCH] * src/muscle_tab.h (MUSCLE_INSERT_INT, MUSCLE_INSERT_STRING) (MUSCLE_INSERT_PREFIX): ...to there. * src/output.c (MUSCLE_INSERT_INT, MUSCLE_INSERT_STRING) (MUSCLE_INSERT_PREFIX): Move from here... * src/bison.hairy: Add a section directive. Put braces around muscle names. This parser skeleton is still broken, but Bison should not choke on a bad muscle 'syntax'. * src/bison.simple: Add a section directive. Put braces around muscle names. * src/files.h (strsuffix, stringappend): Add declarations. (tab_extension): Add declaration. (short_base_name): Add declaration. * src/files.c (strsuffix, stringappend): No longer static. These functions are used in the skeleton parser. (tab_extension): New. (compute_base_names): Use the computations done in this function to guess if the generated parsers should have '.tab' in their names. (short_base_name): No longer static. * src/output.c (output_skeleton): New. (output): Disable call to output_master_parser, and give a try to a new skeleton handling system. (guards_output, actions_output): No longer static. (token_definitions_output, get_lines_number): No longer static. * configure.in: Use AM_PROG_LEX and AC_PROG_YACC. * src/Makefile.am (bison_SOURCES): Add scan-skel.l and parse-skel.y. * src/parse-skel.y: New file. * src/scan-skel.l: New file. --- ChangeLog | 39 +++++++++++ configure.in | 2 + src/Makefile.am | 4 +- src/bison.hairy | 3 +- src/bison.simple | 99 +++++++++++++------------- src/files.c | 21 +++++- src/files.h | 14 ++++ src/muscle_tab.h | 22 ++++++ src/output.c | 56 ++++++++------- src/parse-skel.y | 176 +++++++++++++++++++++++++++++++++++++++++++++++ src/scan-skel.l | 55 +++++++++++++++ 11 files changed, 411 insertions(+), 80 deletions(-) create mode 100644 src/parse-skel.y create mode 100644 src/scan-skel.l diff --git a/ChangeLog b/ChangeLog index 397f44da..1c5ca441 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,42 @@ +2001-12-30 Robert Anisko + + * src/muscle_tab.h (MUSCLE_INSERT_INT, MUSCLE_INSERT_STRING) + (MUSCLE_INSERT_PREFIX): ...to there. + * src/output.c (MUSCLE_INSERT_INT, MUSCLE_INSERT_STRING) + (MUSCLE_INSERT_PREFIX): Move from here... + + * src/bison.hairy: Add a section directive. Put braces around muscle + names. This parser skeleton is still broken, but Bison should not + choke on a bad muscle 'syntax'. + * src/bison.simple: Add a section directive. Put braces around muscle + names. + + * src/files.h (strsuffix, stringappend): Add declarations. + (tab_extension): Add declaration. + (short_base_name): Add declaration. + + * src/files.c (strsuffix, stringappend): No longer static. These + functions are used in the skeleton parser. + (tab_extension): New. + (compute_base_names): Use the computations done in this function + to guess if the generated parsers should have '.tab' in their + names. + (short_base_name): No longer static. + + * src/output.c (output_skeleton): New. + (output): Disable call to output_master_parser, and give a try to + a new skeleton handling system. + (guards_output, actions_output): No longer static. + (token_definitions_output, get_lines_number): No longer static. + + * configure.in: Use AM_PROG_LEX and AC_PROG_YACC. + + * src/Makefile.am (bison_SOURCES): Add scan-skel.l and + parse-skel.y. + + * src/parse-skel.y: New file. + * src/scan-skel.l: New file. + 2001-12-29 Akim Demaille %name-prefix is broken. diff --git a/configure.in b/configure.in index 654b3a91..2cad5761 100644 --- a/configure.in +++ b/configure.in @@ -35,6 +35,8 @@ AC_SUBST([GCC]) # Checks for programs. AC_PROG_CC +AM_PROG_LEX +AC_PROG_YACC AC_MINIX AC_ISC_POSIX AM_PROG_CC_STDC diff --git a/src/Makefile.am b/src/Makefile.am index 05a89fe8..62a1c603 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -23,6 +23,7 @@ DEFS = @DEFS@ \ -DLOCALEDIR=\"$(datadir)/locale\" CFLAGS = @CFLAGS@ $(WARNING_CFLAGS) +YFLAGS = "-dv" # libintl.h in is build/intl, intl/libgettext.h in src/, # config.h in build/. @@ -43,7 +44,8 @@ bison_SOURCES = LR0.c closure.c complain.c conflicts.c \ print_graph.h print_graph.c \ muscle_tab.h muscle_tab.c \ options.h options.c \ - print.c reader.c reduce.c symtab.c warshall.c vcg.c + print.c reader.c reduce.c symtab.c warshall.c vcg.c \ + parse-skel.y scan-skel.l EXTRA_bison_SOURCES = vmsgetargs.c diff --git a/src/bison.hairy b/src/bison.hairy index fc6b68b1..5371ea6f 100644 --- a/src/bison.hairy +++ b/src/bison.hairy @@ -1,3 +1,4 @@ +%%{section} %%{body} %%".c" %%{yacc} /* -*- C -*- */ /* YYERROR and YYCOST are set by guards. If yyerror is set to a @@ -332,4 +333,4 @@ yyerrlab: goto yyresume; } -%%actions +%%{actions} diff --git a/src/bison.simple b/src/bison.simple index 57190178..0482a0ea 100644 --- a/src/bison.simple +++ b/src/bison.simple @@ -1,7 +1,8 @@ +%%{section} %%{body} %%".c" %%{yacc} /* -*- C -*- */ -/* A Bison parser, made from %%filename - by GNU bison %%version. */ +/* A Bison parser, made from %%{filename} + by GNU bison %%{version}. */ /* Skeleton output parser for bison, Copyright 1984, 1989, 1990, 2000, 2001 Free Software Foundation, Inc. @@ -35,31 +36,31 @@ #define YYBISON 1 /* Pure parsers. */ -#define YYPURE %%pure +#define YYPURE %%{pure} /* Using locations. */ -#define YYLSP_NEEDED %%locations-flag +#define YYLSP_NEEDED %%{locations-flag} /* If NAME_PREFIX is specified substitute the variables and functions names. */ -#define yyparse %%prefix##parse -#define yylex %%prefix##lex -#define yyerror %%prefix##error -#define yylval %%prefix##lval -#define yychar %%prefix##char -#define yydebug %%prefix##debug -#define yynerrs %%prefix##nerrs +#define yyparse %%{prefix}parse +#define yylex %%{prefix}lex +#define yyerror %%{prefix}error +#define yylval %%{prefix}lval +#define yychar %%{prefix}char +#define yydebug %%{prefix}debug +#define yynerrs %%{prefix}nerrs #if YYLSP_NEEDED -# define yylloc %%prefix##lloc +# define yylloc %%{prefix}lloc #endif /* Copy the user declarations. */ -%%prologue +%%{prologue} /* Enabling traces. */ #ifndef YYDEBUG -# define YYDEBUG %%debug +# define YYDEBUG %%{debug} #endif /* Enabling verbose error messages. */ @@ -67,11 +68,11 @@ # undef YYERROR_VERBOSE # define YYERROR_VERBOSE 1 #else -# define YYERROR_VERBOSE %%error-verbose +# define YYERROR_VERBOSE %%{error-verbose} #endif #ifndef YYSTYPE -typedef %%stype yystype; +typedef %%{stype} yystype; # define YYSTYPE yystype #endif @@ -83,11 +84,11 @@ typedef struct yyltype int last_line; int last_column; } yyltype; -# define YYLTYPE %%ltype +# define YYLTYPE %%{ltype} #endif -/* Line %%skeleton-line of %%skeleton. */ -#line %%line "%%parser-file-name" +/* Line %%{skeleton-line} of %%{skeleton}. */ +#line %%{line} "%%{parser-file-name}" /* All symbols defined below should begin with yy or YY, to avoid infringing on user name space. This should be done even for local @@ -184,30 +185,30 @@ union yyalloc #endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */ /* Tokens. */ -%%tokendef +%%{tokendef} /* YYFINAL -- State number of the termination state. */ -#define YYFINAL %%final -#define YYFLAG %%flag -#define YYLAST %%last +#define YYFINAL %%{final} +#define YYFLAG %%{flag} +#define YYLAST %%{last} /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS %%ntokens +#define YYNTOKENS %%{ntokens} /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS %%nnts +#define YYNNTS %%{nnts} /* YYNRULES -- Number of rules. */ -#define YYNRULES %%nrules +#define YYNRULES %%{nrules} /* YYNRULES -- Number of states. */ -#define YYNSTATES %%nstates -#define YYMAXUTOK %%maxtok +#define YYNSTATES %%{nstates} +#define YYMAXUTOK %%{maxtok} /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ -#define YYTRANSLATE(x) ((unsigned)(x) <= %%maxtok ? yytranslate[x] : %%nsym) +#define YYTRANSLATE(x) ((unsigned)(x) <= %%{maxtok} ? yytranslate[x] : %%{nsym}) /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ static const char yytranslate[] = { - %%translate + %%{translate} }; #if YYDEBUG @@ -215,19 +216,19 @@ static const char yytranslate[] = YYRHS. */ static const short yyprhs[] = { - %%prhs + %%{prhs} }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const short yyrhs[] = { - %%rhs + %%{rhs} }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const short yyrline[] = { - %%rline + %%{rline} }; #endif @@ -236,26 +237,26 @@ static const short yyrline[] = First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { - %%tname + %%{tname} }; #endif /* YYTOKNUM[YYN] -- Index in YYTNAME corresponding to YYLEX. */ static const short yytoknum[] = { - %%toknum + %%{toknum} }; /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const short yyr1[] = { - %%r1 + %%{r1} }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const short yyr2[] = { - %%r2 + %%{r2} }; /* YYDEFACT[S] -- default rule to reduce with in state S when YYTABLE @@ -263,26 +264,26 @@ static const short yyr2[] = error. */ static const short yydefact[] = { - %%defact + %%{defact} }; /* YYPGOTO[NTERM-NUM]. */ static const short yydefgoto[] = { - %%defgoto + %%{defgoto} }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ static const short yypact[] = { - %%pact + %%{pact} }; /* YYPGOTO[NTERM-NUM]. */ static const short yypgoto[] = { - %%pgoto + %%{pgoto} }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If @@ -290,12 +291,12 @@ static const short yypgoto[] = number is the opposite. If zero, do what YYDEFACT says. */ static const short yytable[] = { - %%table + %%{table} }; static const short yycheck[] = { - %%check + %%{check} }; @@ -419,7 +420,7 @@ int yydebug; /* YYINITDEPTH -- initial size of the parser's stacks. */ #ifndef YYINITDEPTH -# define YYINITDEPTH %%initdepth +# define YYINITDEPTH %%{initdepth} #endif /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only @@ -434,7 +435,7 @@ int yydebug; #endif #ifndef YYMAXDEPTH -# define YYMAXDEPTH %%maxdepth +# define YYMAXDEPTH %%{maxdepth} #endif @@ -903,11 +904,11 @@ yyreduce: #endif switch (yyn) { -%%actions + %%{actions} } -/* Line %%skeleton-line of %%skeleton. */ -#line %%line "%%parser-file-name" +/* Line %%{skeleton-line} of %%{skeleton}. */ +#line %%{line} "%%{parser-file-name}" yyvsp -= yylen; yyssp -= yylen; @@ -1138,4 +1139,4 @@ yyreturn: return yyresult; } -%%epilogue +%%{epilogue} diff --git a/src/files.c b/src/files.c index dc886a0b..2e817b1e 100644 --- a/src/files.c +++ b/src/files.c @@ -51,19 +51,22 @@ char *infile = NULL; char *attrsfile = NULL; static char *base_name = NULL; -static char *short_base_name = NULL; +char *short_base_name = NULL; /* C source file extension (the parser source). */ const char *src_extension = NULL; /* Header file extension (if option ``-d'' is specified). */ const char *header_extension = NULL; + +/* Should we insert '.tab' in yacc-compatible parsers? */ +int tab_extension = 0; /*--------------------------. | Is SUFFIX ending STRING? | `--------------------------*/ -static int +int strsuffix (const char *string, const char *suffix) { size_t string_len = strlen (string); @@ -80,7 +83,7 @@ strsuffix (const char *string, const char *suffix) | STRING1, and STRING2. | `-----------------------------------------------------------------*/ -static char * +char* stringappend (const char *string1, const char *string2) { size_t len = strlen (string1) + strlen (string2); @@ -334,6 +337,11 @@ compute_base_names (void) short_base_length -= 4; short_base_name = strndup (spec_outfile, short_base_length); + /* FIXME: This is a quick and dirty way for me to find out if we + should .tab or not, using the computations above. */ + if (strcmp (base_name, short_base_name)) + tab_extension = 1; + return; } @@ -360,6 +368,10 @@ compute_base_names (void) if (ext_index) compute_exts_from_gf (infile + ext_index); + /* It seems that when only a prefix is given, '.tab' should always be + used. */ + tab_extension = 1; + return; } @@ -393,6 +405,9 @@ compute_base_names (void) strlen (short_base_name) + strlen (EXT_TAB) + 1); stpcpy (stpcpy (base_name, short_base_name), EXT_TAB); + /* By default, Bison should insert '.tab' were needed. */ + tab_extension = 1; + return; } } diff --git a/src/files.h b/src/files.h index 5f02dca1..604216c5 100644 --- a/src/files.h +++ b/src/files.h @@ -68,4 +68,18 @@ char *compute_header_macro PARAMS ((void)); const char *skeleton_find PARAMS ((const char *envvar, const char *skeleton_name)); + +/* Is SUFFIX ending STRING? */ +int strsuffix (const char* string, const char* suffix); + +/* Return a newly allocated string composed of the concatenation of + STRING1, and STRING2. */ +char* stringappend (const char* string1, const char* string2); + +/* Should we insert '.tab' in yacc-compatible parsers? */ +extern int tab_extension; + +/* Prefix used to generate output files names. */ +extern char* short_base_name; + #endif /* !FILES_H_ */ diff --git a/src/muscle_tab.h b/src/muscle_tab.h index c61c6b6a..da35bbd6 100644 --- a/src/muscle_tab.h +++ b/src/muscle_tab.h @@ -33,4 +33,26 @@ void muscle_init PARAMS ((void)); void muscle_insert PARAMS ((const char *key, const char *value)); const char *muscle_find PARAMS ((const char *key)); +#define MUSCLE_INSERT_INT(Key, Value) \ +{ \ + obstack_fgrow1 (&muscle_obstack, "%d", Value); \ + obstack_1grow (&muscle_obstack, 0); \ + muscle_insert (Key, obstack_finish (&muscle_obstack)); \ +} + +#define MUSCLE_INSERT_STRING(Key, Value) \ +{ \ + obstack_sgrow (&muscle_obstack, Value); \ + obstack_1grow (&muscle_obstack, 0); \ + muscle_insert (Key, obstack_finish (&muscle_obstack)); \ +} + +#define MUSCLE_INSERT_PREFIX(Key, Value) \ +{ \ + obstack_fgrow2 (&muscle_obstack, "%s%s", \ + spec_name_prefix ? spec_name_prefix : "yy", Value); \ + obstack_1grow (&muscle_obstack, 0); \ + muscle_insert (Key, obstack_finish (&muscle_obstack)); \ +} + #endif /* not MUSCLE_TAB_H_ */ diff --git a/src/output.c b/src/output.c index 34d6b06a..80fc643b 100644 --- a/src/output.c +++ b/src/output.c @@ -125,7 +125,7 @@ static struct obstack format_obstack; int error_verbose = 0; /* Returns the number of lines of S. */ -static size_t +size_t get_lines_number (const char *s) { size_t lines = 0; @@ -503,7 +503,7 @@ token_actions (void) | Output the actions to OOUT. | `-----------------------------*/ -static void +void actions_output (FILE *out, size_t *line) { int rule; @@ -539,7 +539,7 @@ actions_output (FILE *out, size_t *line) | Output the guards to OOUT. | `----------------------------*/ -static void +void guards_output (FILE *out, size_t *line) { int rule; @@ -571,7 +571,7 @@ guards_output (FILE *out, size_t *line) | Output the tokens definition to OOUT. | `---------------------------------------*/ -static void +void token_definitions_output (FILE *out, size_t *line) { int i; @@ -1042,6 +1042,11 @@ static void output_master_parser (void) { FILE *parser = xfopen (parser_file_name, "w"); + + /* FIXME: Remove the two following lines. */ + printf ("Test: %s\n", infile); + printf ("Test: %s\n", parser_file_name); + if (!skeleton) { if (semantic_parser) @@ -1056,29 +1061,24 @@ output_master_parser (void) xfclose (parser); } +/* Call the skeleton parser. */ -/* FIXME. */ - -#define MUSCLE_INSERT_INT(Key, Value) \ -{ \ - obstack_fgrow1 (&muscle_obstack, "%d", Value); \ - obstack_1grow (&muscle_obstack, 0); \ - muscle_insert (Key, obstack_finish (&muscle_obstack)); \ -} - -#define MUSCLE_INSERT_STRING(Key, Value) \ -{ \ - obstack_sgrow (&muscle_obstack, Value); \ - obstack_1grow (&muscle_obstack, 0); \ - muscle_insert (Key, obstack_finish (&muscle_obstack)); \ -} +static +void +output_skeleton () +{ + /* Find the right skeleton file. */ + if (!skeleton) + { + if (semantic_parser) + skeleton = skeleton_find ("BISON_HAIRY", BISON_HAIRY); + else + skeleton = skeleton_find ("BISON_SIMPLE", BISON_SIMPLE); + } -#define MUSCLE_INSERT_PREFIX(Key, Value) \ -{ \ - obstack_fgrow2 (&muscle_obstack, "%s%s", \ - spec_name_prefix ? spec_name_prefix : "yy", Value); \ - obstack_1grow (&muscle_obstack, 0); \ - muscle_insert (Key, obstack_finish (&muscle_obstack)); \ + /* Parse the skeleton file and output the needed parsers. */ + muscle_insert ("skeleton", skeleton); + process_skeleton (infile, skeleton); } static void @@ -1102,7 +1102,6 @@ prepare (void) MUSCLE_INSERT_INT ("locations-flag", locations_flag); } - /*-------------------------. | Output the header file. | `-------------------------*/ @@ -1188,8 +1187,13 @@ output (void) obstack_1grow (&attrs_obstack, 0); muscle_insert ("prologue", obstack_finish (&attrs_obstack)); + /* Process the selected skeleton file. */ + output_skeleton (); + /* Output the parser. */ +#if 0 output_master_parser (); +#endif /* Output the header if needed. */ if (defines_flag) header_output (); diff --git a/src/parse-skel.y b/src/parse-skel.y new file mode 100644 index 00000000..9223485e --- /dev/null +++ b/src/parse-skel.y @@ -0,0 +1,176 @@ +%{ + +#include "system.h" +#include "obstack.h" +#include "files.h" + +#include "muscle_tab.h" + +#define YYDEBUG 1 +#define YYERROR_VERBOSE 1 + +extern FILE* yyin; +extern int yylineno; + +char* prefix = NULL; +FILE* parser = NULL; + +size_t output_line; +size_t skeleton_line; + +extern struct obstack muscle_obstack; + +%} + +%union +{ + char* muscle; + char* string; + char character; + int yacc; +} + +%token< muscle > MUSCLE +%token< string > STRING +%token< character > CHARACTER + +%token LINE +%token SLINE + +%token YACC +%token SECTION + +%token GUARDS +%token TOKENS +%token ACTIONS + +%type< yacc > section.yacc + +%start skeleton + +%% + +skeleton : /* Empty. */ { } + | section skeleton { } +; + +section : section.header section.body { } +; + +section.header : SECTION gb MUSCLE gb STRING gb section.yacc gb '\n' +{ + char* name = 0; + char* limit = 0; + char* suffix = $5; + + /* Close the previous parser. */ + if (parser) + parser = (xfclose (parser), NULL); + + /* If the following section should be named with the yacc-style, and it's + suffix is of the form 'something.h' or 'something.c', then add '.tab' in + the middle of the suffix. */ + if (tab_extension && $7 && (strsuffix (suffix, ".h") || + strsuffix (suffix, ".c"))) + { + size_t prefix_len = strlen (prefix); + size_t suffix_len = strlen (suffix); + + /* Allocate enough space to insert '.tab'. */ + name = XMALLOC (char, prefix_len + suffix_len + 5); + limit = strrchr (suffix, '.'); + if (!limit) + limit = suffix; + + /* Prefix is 'X', suffix is 'Y.Z'. Name will be 'XY.tab.Z'. */ + { + char* cp = 0; + cp = stpcpy (name, prefix); + cp = stpncpy (cp, suffix, limit - suffix); + cp = stpcpy (cp, ".tab"); + cp = stpcpy (cp, limit); + } + } + else + name = stringappend (prefix, suffix); + + /* Prepare the next parser to be output. */ + parser = xfopen (name, "w"); + MUSCLE_INSERT_STRING ("parser-file-name", name); + XFREE (name); + + ++skeleton_line; +} +; + +section.yacc : /* Empty. */ { $$ = 0; } + | YACC { $$ = 1; } +; + +section.body +: /* Empty. */ { } +| section.body '\n' { fputc ('\n', parser); ++output_line; ++skeleton_line; } +| section.body LINE { fprintf (parser, "%d", output_line); } +| section.body SLINE { fprintf (parser, "%d", skeleton_line); } +| section.body GUARDS { guards_output (parser, &output_line); } +| section.body TOKENS { token_definitions_output (parser, &output_line); } +| section.body ACTIONS { actions_output (parser, &output_line); } +| section.body CHARACTER { fputc ($2, parser); } +| section.body MUSCLE { + const char* value = muscle_find ($2); + if (value) + { + fputs (value, parser); + output_line += get_lines_number (value); + } + else + { + fprintf (parser, "%%{%s}", $2); + merror ($2); + } +} +; + +gb : /* Empty. */ { } + | gb CHARACTER { /* Do not echo garbage characters. */ } +; + +%% + +int +merror (const char* error) +{ + printf ("line %d: %%{%s} undeclared.\n", skeleton_line, error); + return 0; +} + +int +yyerror (const char* error) +{ + printf ("line %d: %s.\n", yylineno, error); + return 0; +} + +int +process_skeleton (const char* grammar, + const char* skeleton) +{ + const char* limit = 0; + + /* Compute prefix. Actually, it seems that the processing I need here is + done in compute_base_names, and the result stored in short_base_name. */ + prefix = short_base_name; + + /* Prepare a few things. */ + output_line = 1; + skeleton_line = 1; + + /* Output. */ + yyin = fopen (skeleton, "r"); + yydebug = 0; + yyparse (); + + /* Close the last parser. */ + if (parser) + parser = (xfclose (parser), NULL); +} diff --git a/src/scan-skel.l b/src/scan-skel.l new file mode 100644 index 00000000..b78e02f5 --- /dev/null +++ b/src/scan-skel.l @@ -0,0 +1,55 @@ +%{ + +#include +#include + +#include "parse-skel.h" + +%} + +%option nounput +%option noyywrap +%option yylineno + +%% + +"%%{line}" { return LINE; } +"%%{skeleton-line}" { return SLINE; } + +"%%{yacc}" { return YACC; } +"%%{section}" { return SECTION; } + +"%%{guards}" { return GUARDS; } +"%%{actions}" { return ACTIONS; } +"%%{tokendef}" { return TOKENS; } + +"%%{"[a-zA-Z][0-9a-zA-Z_-]+"}" { /* Muscle. */ + size_t len = strlen (yytext); + yylval.string = (char*) malloc (len - 3); + strncpy (yylval.string, yytext + 3, len - 4); + yylval.string[len - 4] = 0; + return MUSCLE; +} + +"%%\"".*"\"" { /* String. */ + size_t len = strlen (yytext); + yylval.string = (char*) malloc (len - 3); + strncpy (yylval.string, yytext + 3, len - 4); + yylval.string[len - 4] = 0; + return STRING; +} + +<> { /* End of file. */ + return 0; +} + +"\n" { /* End of line. */ + return '\n'; +} + +. { /* Character. */ + yylval.character = *yytext; + return CHARACTER; +} + +%% -- 2.45.2