Refactor lexer and parser for maintainability

- Speedmode is now purely a parser thing
- Lexer start condition SPEEDMODE is no longer needed
- Added lexer start condition BOX to distinguish box def content
- DELIMs are now purely a lexer thing
- No shared state between lexer and parser for DELIMs anymore
- Fix bug where speedmode could terminate in a SAMPLE block
- All lexer start conditions now exclusive
- Improved debug output
- Renamed parser token YDELWORD to YDELIMSPEC
This commit is contained in:
Thomas Jensen 2021-06-13 14:50:34 +02:00
parent 00153f8068
commit 2d3a842728
No known key found for this signature in database
GPG Key ID: A4ACEE270D0FB7DB
9 changed files with 216 additions and 179 deletions

View File

@ -29,16 +29,20 @@
typedef struct {
int yyerrcnt;
/** pointer to the currently active string delimiter character in bison_args */
char *sdel_ptr;
/** the currently active string delimiter character */
char sdel;
/** pointer to the currently active string escape character in bison_args */
char *sesc_ptr;
/** the currently active string escape character */
char sesc;
} pass_to_flex;
void begin_speedmode(void *yyscanner);
/*
* Valid characters to be used as string delimiters. Note that the
* following list must correspond to the SDELIM definition below.
*/
#define LEX_SDELIM "\"~'`!@%&*=:;<>?/|.\\"
#define LEX_SDELIM_RECOMMENDED "\"~'!|"
/**
@ -73,6 +77,8 @@ static void report_state_char(char *symbol, char c, char *expected_state_str);
static void report_state(char *symbol, char *text, char *expected_state_str);
static int change_string_delimiters(pass_to_flex *extra, char *delim_expr);
%}
@ -91,17 +97,16 @@ static void report_state(char *symbol, char *text, char *expected_state_str);
%option yylineno
%x DELWORD
%x PARENT
%x BOX
%x SAMPLE
%x SPEEDMODE
%s ELASTIC
%s SHAPES
%x SHAPES
%x ELASTIC
%x DELIMSPEC
%x PARENT
PWORD [a-zA-ZäöüÄÖÜ][a-zA-Z0-9\-_üäöÜÄÖß]*
PWHITE [\n \r\t]
PBOX Box
PWHITE [ \t\r\n]
SDELIM [\"~\'`!@\%\&\*=:;<>\?/|\.\\]
PPARENT parent
PFILENAME [^\r\n]+
@ -109,38 +114,39 @@ PFILENAME [^\r\n]+
%%
<INITIAL,DELWORD,ELASTIC,SHAPES>[ \r\t] /* ignore whitespace */
<INITIAL,DELWORD,ELASTIC,SHAPES>\n {}
<DELWORD>[^ \t\r\n]+ {
/*
* String delimiter spec - like WORD, but allow any character
* Precedence of rules:
* - The rule that matches the most text wins.
* - If two rules match the same amount of text, the one defined first (further up) wins.
*/
<INITIAL,BOX,DELIMSPEC,ELASTIC,SHAPES>{PWHITE} /* ignore whitespace */
<DELIMSPEC>[^ \t\r\n]+ {
/*
* String delimiter spec - like WORD, but allow any character
*/
yylval->s = (char *) strdup (yytext);
if (yylval->s == NULL) {
perror (PROJECT);
exit (EXIT_FAILURE);
BEGIN(BOX);
report_state("YDELIMS", yytext, "INITIAL");
if (change_string_delimiters(yyextra, yylval->s) != 0) {
return YUNREC;
}
BEGIN(INITIAL);
report_state("YDELWOR", yytext, "INITIAL");
return YDELWORD;
return YDELIMSPEC;
}
{SDELIM}.*$ {
<BOX,SHAPES>{SDELIM}.*$ {
/*
* Strings -- first match everything starting from a potential
* string delimiter until the end of the line. We will give back what
* we don't need and also detect unterminated strings.
* Strings -- first match everything starting from a potential string delimiter until the end of the line. We
* will give back what we don't need and also detect unterminated strings. Strings always end on the same line.
*/
char *p;
int rest_len = yyleng - 1; /* length of string pointed to by p */
int qcnt = 0; /* esc char count in current string */
if (yytext[0] != *(yyextra->sdel_ptr)) {
if (yytext[0] != yyextra->sdel) {
REJECT; /* that was not our delimiter */
}
@ -152,14 +158,14 @@ PFILENAME [^\r\n]+
p = yylval->s;
while (*p) {
if (*p == *(yyextra->sesc_ptr)) {
if (*p == yyextra->sesc) {
memmove (p, p+1, rest_len); /* incl. '\0' */
++qcnt;
--rest_len;
if (*p == '\0')
break;
}
else if (*p == *(yyextra->sdel_ptr)) {
else if (*p == yyextra->sdel) {
*p = '\0';
yyless ((p-yylval->s)+2+qcnt); /* string plus quotes */
#ifdef LEXER_DEBUG
@ -177,7 +183,7 @@ PFILENAME [^\r\n]+
}
{PPARENT} {
<INITIAL>{PPARENT} {
BEGIN(PARENT);
report_state("YPARENT", yytext, "PARENT");
return YPARENT;
@ -204,19 +210,18 @@ PFILENAME [^\r\n]+
report_state(" NL", "", "INITIAL");
}
Sample {
<BOX>Sample {
BEGIN(SAMPLE);
report_state("YSAMPLE", yytext, "SAMPLE");
return YSAMPLE;
}
<SAMPLE>\n {
if (yyleng > 1)
yymore();
}
<SAMPLE>^[ \t]*ends[ \t\r]*$ {
char *p = yytext + yyleng -1;
size_t len; /* length of sample */
@ -239,8 +244,6 @@ Sample {
btrim (yylval->s, &len);
if (len > 0) {
strcat (yylval->s, "\n"); /* memory was allocated with strdup */
BEGIN(INITIAL);
report_state(" STRING", yylval->s, "INITIAL");
return STRING;
}
else {
@ -252,53 +255,56 @@ Sample {
}
}
<SAMPLE>. yymore();
ends[ \t\r]*$ {
#ifdef LEXER_DEBUG
fprintf (stderr, "YENDSAM: %s\n", yytext);
#endif
<SAMPLE>ends[ \t\r]*$ {
/* reached because the other rule pushes it back so a proper end token can be returned */
BEGIN(BOX);
report_state("YENDSAM", yytext, "BOX");
return YENDSAMPLE;
}
Tags {
<BOX>Tags {
#ifdef LEXER_DEBUG
fprintf (stderr, " YTAGS: %s\n", yytext);
#endif
return YTAGS;
}
Elastic {
<BOX>Elastic {
BEGIN(ELASTIC);
report_state("YELASTC", yytext, "ELASTIC");
return YELASTIC;
}
Shapes {
<BOX>Shapes {
BEGIN(SHAPES);
report_state("YSHAPES", yytext, "SHAPES");
return YSHAPES;
}
{PBOX} {
#ifdef LEXER_DEBUG
fprintf (stderr, " YBOX: %s\n", yytext);
#endif
<INITIAL>Box {
BEGIN(BOX);
report_state(" YBOX", yytext, "BOX");
yyextra->yyerrcnt = 0;
change_string_delimiters(yyextra, "\\\"");
return YBOX;
}
Replace { return YREPLACE; }
Reverse { return YREVERSE; }
Padding { return YPADDING; }
End { return YEND; }
To { return YTO; }
With { return YWITH; }
Global { yylval->c = 'g'; return YRXPFLAG; }
Once { yylval->c = 'o'; return YRXPFLAG; }
<BOX>Replace { return YREPLACE; }
<BOX>Reverse { return YREVERSE; }
<BOX>Padding { return YPADDING; }
<BOX>To { return YTO; }
<BOX>With { return YWITH; }
<BOX>Global { yylval->c = 'g'; return YRXPFLAG; }
<BOX>Once { yylval->c = 'o'; return YRXPFLAG; }
<BOX>End {
BEGIN(INITIAL);
report_state(" YEND", yytext, "INITIAL");
change_string_delimiters(yyextra, "\\\"");
return YEND;
}
<SHAPES,ELASTIC>nw { yylval->shape = NW; return SHAPE; }
@ -319,21 +325,21 @@ Once { yylval->c = 'o'; return YRXPFLAG; }
<SHAPES,ELASTIC>wnw { yylval->shape = WNW; return SHAPE; }
<ELASTIC>\) {
BEGIN(INITIAL);
report_state_char("SYMBOL", yytext[0], "INITIAL");
BEGIN(BOX);
report_state_char("SYMBOL", yytext[0], "BOX");
return yytext[0];
}
<SHAPES>\} {
BEGIN(INITIAL);
report_state_char("SYMBOL", yytext[0], "INITIAL");
BEGIN(BOX);
report_state_char("SYMBOL", yytext[0], "BOX");
return yytext[0];
}
author|designer|created|revision|revdate|indent {
<BOX>author|designer|created|revision|revdate|indent {
/*
* general key words
* general key words
*/
#ifdef LEXER_DEBUG
fprintf (stderr, "KEYWORD: %s\n", yytext);
@ -347,17 +353,20 @@ author|designer|created|revision|revdate|indent {
}
Delimiter|Delim {
<BOX>Delimiter|Delim {
/*
* Change string delimiting characters
* Change string delimiting characters
*/
BEGIN(DELWORD);
report_state("YCHGDEL", yytext, "DELWORD");
BEGIN(DELIMSPEC);
report_state("YCHGDEL", yytext, "DELIMSPEC");
return YCHGDEL;
}
{PWORD} {
<INITIAL,BOX>{PWORD} {
/*
* a free-floating word which is not a string, i.e. it does not have delimiting characters
*/
#ifdef LEXER_DEBUG
fprintf (stderr, " WORD: %s\n", yytext);
#endif
@ -370,7 +379,7 @@ Delimiter|Delim {
}
[\+-]?[0-9]+ {
<BOX>[\+-]?[0-9]+ {
#ifdef LEXER_DEBUG
fprintf (stderr, "YNUMBER: %s\n", yytext);
#endif
@ -379,7 +388,7 @@ Delimiter|Delim {
}
[,(){}] {
<BOX,SHAPES,ELASTIC>[,(){}] {
#ifdef LEXER_DEBUG
fprintf (stderr, " SYMBOL: \'%c\'\n", yytext[0]);
#endif
@ -387,7 +396,7 @@ Delimiter|Delim {
}
#.*$ {
<INITIAL,BOX,SHAPES,ELASTIC>#.*$ {
/* ignore comments */
#ifdef LEXER_DEBUG
fprintf (stderr, "COMMENT: %s\n", yytext+1);
@ -395,25 +404,15 @@ Delimiter|Delim {
}
. {
if ((yyextra->yyerrcnt)++ < LEX_MAX_WARN)
yyerror(NULL, "Unrecognized input char \'%s\'", yytext);
<INITIAL,BOX,SHAPES,ELASTIC>. {
/* a character that made no sense where it was encountered. Let the parser handle it. */
#ifdef LEXER_DEBUG
fprintf (stderr, " YUNREC: \'%c\'\n", yytext[0]);
#endif
return YUNREC;
}
<SPEEDMODE>{PBOX}{PWHITE}+{PWORD}|{PPARENT} {
/* end speedmode, but then give back the whole match so BOX or PARENT can be started properly */
yyless(0);
BEGIN(INITIAL);
report_state(" STATUS", "", "INITIAL");
}
<SPEEDMODE>\n {}
<SPEEDMODE>. /* ignore anything else */
%%
@ -433,19 +432,10 @@ void inflate_inbuf(void *yyscanner, const char *configfile)
void begin_speedmode(void *yyscanner)
{
struct yyguts_t *yyg = (struct yyguts_t *) yyscanner;
BEGIN(SPEEDMODE);
report_state(" STATUS", "begin_speedmode()", "SPEEDMODE");
}
static void report_state_char(char *symbol, char c, char *expected_state_str)
{
char *s = (char *) malloc(4);
sprintf(s, "'%c'", c);
sprintf(s, "'%c'", c >= ' ' && c <= 126 ? c : '?');
report_state(symbol, s, expected_state_str);
BFREE(s);
}
@ -464,4 +454,30 @@ static void report_state(char *symbol, char *text, char *expected_state_str)
}
static int change_string_delimiters(pass_to_flex *extra, char *delim_expr)
{
if (strlen(delim_expr) != 2) {
yyerror(NULL, "invalid string delimiter specification -- %s", delim_expr);
return 1;
}
if (delim_expr[0] == delim_expr[1]) {
yyerror(NULL, "string delimiter and escape char may not be the same");
return 1;
}
if (strchr (LEX_SDELIM, delim_expr[1]) == NULL) {
yyerror(NULL, "invalid string delimiter -- %c (try one of %s)", delim_expr[1], LEX_SDELIM_RECOMMENDED);
return 1;
}
#ifdef LEXER_DEBUG
fprintf(stderr, "YDELIMS: change_string_delimiters('%c', '%c')\n", delim_expr[0], delim_expr[1]);
#endif
extra->sesc = delim_expr[0];
extra->sdel = delim_expr[1];
return 0;
}
/*EOF*/ /* vim: set cindent sw=4: */

View File

@ -39,48 +39,11 @@
#include "lex.yy.h"
/*
* Valid characters to be used as string delimiters. Note that the
* following list must correspond to the DELIM definition in lexer.l.
*/
#define LEX_SDELIM "\"~'`!@%&*=:;<>?/|.\\"
static pcre2_code *eol_pattern = NULL;
static void chg_strdelims (pass_to_bison *bison_args, const char asesc, const char asdel)
{
#ifdef PARSER_DEBUG
fprintf (stderr, " STATUS: chg_strdelims ('%c', '%c') - This changes lexer behavior!\n", asesc, asdel);
#endif
bison_args->sesc = asesc;
bison_args->sdel = asdel;
}
int action_chg_delim(pass_to_bison *bison_args, char *delim_expr)
{
if (strlen(delim_expr) != 2) {
yyerror(bison_args, "invalid string delimiter specification -- %s", delim_expr);
return RC_ERROR;
}
if (delim_expr[0] == delim_expr[1]) {
yyerror(bison_args, "string delimiter and escape char may not be the same");
return RC_ERROR;
}
if (strchr (LEX_SDELIM, delim_expr[1]) == NULL) {
yyerror(bison_args, "invalid string delimiter -- %c (try one of %s)",
delim_expr[1], LEX_SDELIM);
return RC_ERROR;
}
chg_strdelims(bison_args, delim_expr[0], delim_expr[1]);
return RC_SUCCESS;
}
static int check_sizes(pass_to_bison *bison_args)
/*
* For the author's convenience, it is required that shapes on one side
@ -95,7 +58,7 @@ static int check_sizes(pass_to_bison *bison_args)
int i, j, k;
#ifdef PARSER_DEBUG
fprintf (stderr, "check_sizes()\n");
fprintf (stderr, " Parser: check_sizes()\n");
#endif
for (i=0; i<NUM_SIDES; ++i) {
@ -163,7 +126,7 @@ static int corner_check(pass_to_bison *bison_args)
int c;
#ifdef PARSER_DEBUG
fprintf (stderr, "corner_check()\n");
fprintf (stderr, " Parser: corner_check()\n");
#endif
for (c=0; c<NUM_CORNERS; ++c) {
@ -183,7 +146,7 @@ static shape_t non_existent_elastics(pass_to_bison *bison_args)
shape_t i;
#ifdef PARSER_DEBUG
fprintf (stderr, "non_existent_elastics()\n");
fprintf (stderr, " Parser: non_existent_elastics()\n");
#endif
for (i=0; i<NUM_SHAPES; ++i) {
@ -202,7 +165,7 @@ static int insufficient_elasticity(pass_to_bison *bison_args)
int i, j, ef;
#ifdef PARSER_DEBUG
fprintf (stderr, "insufficient_elasticity()\n");
fprintf (stderr, " Parser: insufficient_elasticity()\n");
#endif
for (i=0; i<NUM_SIDES; ++i) {
@ -226,7 +189,7 @@ static int adjoining_elastics(pass_to_bison *bison_args)
int i, j, ef;
#ifdef PARSER_DEBUG
fprintf (stderr, "adjoining_elastics()\n");
fprintf (stderr, " Parser: adjoining_elastics()\n");
#endif
for (i=0; i<NUM_SIDES; ++i) {
@ -304,7 +267,6 @@ void recover(pass_to_bison *bison_args)
bison_args->num_mandatory = 0;
bison_args->time_for_se_check = 0;
bison_args->num_shapespec = 0;
chg_strdelims(bison_args, '\\', '\"');
/*
* Clear current design
@ -358,7 +320,7 @@ static int full_parse_required()
result = opt.r || opt.l || (opt.query != NULL && !query_is_undoc());
}
#ifdef DEBUG
fprintf(stderr, "full_parse_required() -> %s\n", result ? "true" : "false");
fprintf(stderr, " Parser: full_parse_required() -> %s\n", result ? "true" : "false");
#endif
return result;
}
@ -642,9 +604,9 @@ int action_finalize_shapes(pass_to_bison *bison_args)
}
}
#ifdef PARSER_DEBUG
fprintf (stderr, "Minimum box dimensions: width %d height %d\n",
fprintf (stderr, " Parser: Minimum box dimensions: width %d height %d\n",
(int) curdes.minwidth, (int) curdes.minheight);
fprintf (stderr, "Maximum shape height: %d\n",
fprintf (stderr, " Parser: Maximum shape height: %d\n",
(int) curdes.maxshapeheight);
#endif
return RC_SUCCESS;
@ -662,7 +624,6 @@ int action_finalize_shapes(pass_to_bison *bison_args)
*/
int action_start_parsing_design(pass_to_bison *bison_args, char *design_name)
{
chg_strdelims(bison_args, '\\', '\"');
bison_args->speeding = 0;
bison_args->skipping = 0;
@ -674,9 +635,10 @@ int action_start_parsing_design(pass_to_bison *bison_args, char *design_name)
if (!design_needed(bison_args)) {
bison_args->speeding = 1;
begin_speedmode(bison_args->lexer_state);
init_design(bison_args, &(curdes));
return RC_ERROR;
#ifdef PARSER_DEBUG
fprintf (stderr, " Parser: Skipping to next design (lexer doesn't know!)\n");
#endif
return RC_ERROR; /* trigger the parser's `error` rule, which will skip to the next design */
}
return RC_SUCCESS;
}
@ -693,7 +655,7 @@ int action_start_parsing_design(pass_to_bison *bison_args, char *design_name)
int action_parent_config(pass_to_bison *bison_args, char *filepath)
{
#ifdef PARSER_DEBUG
fprintf (stderr, "parent config file specified: [%s]\n", filepath);
fprintf (stderr, " Parser: parent config file specified: [%s]\n", filepath);
#endif
if (filepath == NULL || filepath[0] == '\0') {
bison_args->skipping = 1;
@ -720,13 +682,13 @@ int action_parent_config(pass_to_bison *bison_args, char *filepath)
}
}
#ifdef PARSER_DEBUG
fprintf (stderr, "parent config file path resolved: [%s]\n", filepath);
fprintf (stderr, " Parser: parent config file path resolved: [%s]\n", filepath);
#endif
int is_new = !array_contains(bison_args->parent_configs, bison_args->num_parent_configs, filepath);
if (!is_new) {
#ifdef PARSER_DEBUG
fprintf (stderr, "duplicate parent / cycle: [%s]\n", filepath);
fprintf (stderr, " Parser: duplicate parent / cycle: [%s]\n", filepath);
#endif
}
else {
@ -822,7 +784,7 @@ int action_add_design(pass_to_bison *bison_args, char *design_primary_name, char
int action_record_keyword(pass_to_bison *bison_args, char *keyword, char *value)
{
#ifdef PARSER_DEBUG
fprintf (stderr, "entry rule fulfilled [%s = %s]\n", keyword, value);
fprintf (stderr, " Parser: entry rule fulfilled [%s = %s]\n", keyword, value);
#endif
if (strcasecmp (keyword, "author") == 0) {
curdes.author = (char *) strdup (value);
@ -946,7 +908,7 @@ int action_add_alias(pass_to_bison *bison_args, char *alias_name)
}
if (alias_exists_in_child_configs(bison_args, alias_name)) {
#ifdef PARSER_DEBUG
fprintf (stderr, "alias already used by child config, dropping: %s\n", alias_name);
fprintf (stderr, " Parser: alias already used by child config, dropping: %s\n", alias_name);
#endif
}
else {
@ -978,7 +940,7 @@ static char *adjust_eols(char *sample)
int action_sample_block(pass_to_bison *bison_args, char *sample)
{
#ifdef PARSER_DEBUG
fprintf(stderr, "SAMPLE block rule satisfied\n");
fprintf(stderr, " Parser: SAMPLE block rule satisfied\n");
#endif
if (curdes.sample) {

View File

@ -48,9 +48,6 @@
int action_init_parser(pass_to_bison *bison_args);
int action_chg_delim(pass_to_bison *bison_args, char *delim_expr);
/**
* Rule action called when a shape list was fully parsed.
* @param bison_args the parser state

View File

@ -47,12 +47,6 @@ typedef struct {
/** the path to the config file we are parsing */
char *config_file;
/** the currently active string delimiter character */
char sdel;
/** the currently active string escape character */
char sesc;
int num_mandatory;
int time_for_se_check;
@ -140,7 +134,7 @@ typedef struct {
%token <shape> SHAPE
%token <num> YNUMBER
%token <c> YRXPFLAG
%token <s> YDELWORD
%token <s> YDELIMSPEC
%type <sentry> shape_def
%type <sentry> shape_lines
@ -203,7 +197,16 @@ config_file: config_file design_or_error | design_or_error | config_file parent_
design_or_error: design | error
{
if (!(bison_args->speeding) && !(bison_args->skipping)) {
/* reset alias list, as those are collected even when speedmode is on */
#ifdef PARSER_DEBUG
fprintf (stderr, " Parser: Discarding token [skipping=%s, speeding=%s]\n",
bison_args->skipping ? "true" : "false", bison_args->speeding ? "true" : "false");
#endif
if (curdes.aliases[0] != NULL) {
BFREE(curdes.aliases);
curdes.aliases = (char **) calloc(1, sizeof(char *));
}
if (!bison_args->speeding && !bison_args->skipping) {
recover(bison_args);
yyerror(bison_args, "skipping to next design");
bison_args->skipping = 1;
@ -260,14 +263,14 @@ entry: KEYWORD STRING
}
else {
#ifdef PARSER_DEBUG
fprintf (stderr, "%s: Discarding entry [%s = %s].\n", PROJECT, "parent", filename);
fprintf (stderr, " Parser: Discarding entry [%s = %s].\n", "parent", filename);
#endif
}
}
| YCHGDEL YDELWORD
| YCHGDEL YDELIMSPEC
{
invoke_action(action_chg_delim(bison_args, $2));
/* string delimiters were changed - this is a lexer thing. ignore here. */
}
| YTAGS '(' tag_list ')' | YTAGS tag_entry
@ -275,7 +278,7 @@ entry: KEYWORD STRING
| WORD STRING
{
#ifdef PARSER_DEBUG
fprintf (stderr, "%s: Discarding entry [%s = %s].\n", PROJECT, $1, $2);
fprintf (stderr, " Parser: Discarding entry [%s = %s].\n", $1, $2);
#endif
}
;
@ -492,4 +495,5 @@ wlist_entry: WORD YNUMBER
%%
/*EOF*/ /* vim: set sw=4 cindent: */

View File

@ -135,8 +135,6 @@ static pass_to_bison new_bison_args(const char *config_file)
bison_args.num_designs = 0;
bison_args.design_idx = 0;
bison_args.config_file = (char *) config_file;
bison_args.sdel = '\"'; /* sdel is shared by flex and bison */
bison_args.sesc = '\\'; /* sesc is shared by flex and bison */
bison_args.num_mandatory = 0;
bison_args.time_for_se_check = 0;
bison_args.num_shapespec = 0;
@ -150,12 +148,12 @@ static pass_to_bison new_bison_args(const char *config_file)
static pass_to_flex new_flex_extra_data(pass_to_bison *bison_args)
static pass_to_flex new_flex_extra_data()
{
pass_to_flex flex_extra_data;
flex_extra_data.yyerrcnt = 0;
flex_extra_data.sdel_ptr = &(bison_args->sdel);
flex_extra_data.sesc_ptr = &(bison_args->sesc);
flex_extra_data.sdel = '\"';
flex_extra_data.sesc = '\\';
return flex_extra_data;
}
@ -170,7 +168,7 @@ static pass_to_bison parse_config_file(const char *config_file, design_t *child_
pass_to_bison bison_args = new_bison_args(config_file);
bison_args.child_configs = child_configs;
bison_args.num_child_configs = num_child_configs;
pass_to_flex flex_extra_data = new_flex_extra_data(&bison_args);
pass_to_flex flex_extra_data = new_flex_extra_data();
current_bison_args = &bison_args;
yylex_init (&(bison_args.lexer_state));

View File

@ -11,7 +11,7 @@ that speedmode is properly terminated.)
:EXPECTED
boxes: 131_data/B.cfg: line 32: entries SAMPLE, SHAPES, and ELASTIC are mandatory
boxes: 131_data/B.cfg: line 32: skipping to next design
boxes: 131_data/A.cfg: line 29: string expected
boxes: 131_data/A.cfg: line 29: syntax error
boxes: 131_data/A.cfg: line 29: skipping to next design
3 Available Styles:
-------------------

View File

@ -1,5 +1,5 @@
:DESC
Test that the list of aliases is properly reset when lexer is in speedmode.
Test that the list of aliases is properly reset when parser is in speedmode.
:ARGS
-f 137_design_alias_no_accumulation.cfg -d alias3b -l

View File

@ -0,0 +1,33 @@
BOX designA
sample
A mentions the word parent THIS_IS_NOT_A_CONFIG_FILE
ends
shapes {
w ("A")
}
elastic (
w
)
END designA
BOX designB
sample
B is the one we select
ends
shapes {
w ("B")
}
elastic (
w
)
END designB

View File

@ -0,0 +1,27 @@
:DESC
Test that the keyword 'parent' may occur as a regular string in a sample block, without triggering parent config file
resolution.
:ARGS
-f 168_parent_keyword_in_sample_ok.cfg -d designB -l
:INPUT
:OUTPUT-FILTER
:EXPECTED
Complete Design Information for "designB":
------------------------------------------
Alias Names: none
Author: (unknown author)
Original Designer: (unknown artist)
Creation Date: (unknown)
Current Revision: (unknown)
Configuration File: 168_parent_keyword_in_sample_ok.cfg
Indentation Mode: box (indent box)
Replacement Rules: none
Reversion Rules: none
Minimum Box Dimensions: 3 x 3 (width x height)
Default Padding: none
Default Killblank: no
Tags: none
Elastic Shapes: N, E, S, W
Defined Shapes: W: "B"
:EOF