1/*
2 * Copyright 1993, 2000 Christopher Seiwald.
3 *
4 * This file is part of Jam - see jam.c for Copyright information.
5 */
6
7/*
8 * parse.c - make and destroy parse trees as driven by the parser
9 *
10 * 09/07/00 (seiwald) - ref count on PARSE to avoid freeing when used,
11 *		as per Matt Armstrong.
12 * 09/11/00 (seiwald) - structure reworked to reflect that (*func)()
13 *		returns a LIST *.
14 * 10/22/02 (seiwald) - working return/break/continue statements
15 * 11/04/02 (seiwald) - const-ing for string literals
16 */
17
18# include "jam.h"
19# include "lists.h"
20# include "parse.h"
21# include "scan.h"
22# include "newstr.h"
23# include "compile.h"
24
25static PARSE *yypsave;
26
27void
28parse_file( const char *f )
29{
30	/* Suspend scan of current file */
31	/* and push this new file in the stream */
32
33	yyfparse(f);
34
35	/* Now parse each block of rules and execute it. */
36	/* Execute it outside of the parser so that recursive */
37	/* calls to yyrun() work (no recursive yyparse's). */
38
39	for(;;)
40	{
41	    LOL l;
42	    PARSE *p;
43	    int jmp = 0; /* JMP_NONE */
44
45	    /* $(<) and $(>) empty in outer scope. */
46
47	    lol_init( &l );
48
49	    /* Filled by yyparse() calling parse_save() */
50
51	    yypsave = 0;
52
53	    /* If parse error or empty parse, outta here */
54
55	    if( yyparse() || !( p = yypsave ) )
56		break;
57
58	    /* Run the parse tree. */
59
60	    list_free( (*(p->func))( p, &l, &jmp ) );
61
62	    parse_free( p );
63
64	    if ( jmp == JMP_EOF )
65		break;
66	}
67}
68
69void
70parse_save( PARSE *p )
71{
72	yypsave = p;
73}
74
75PARSE *
76parse_make(
77	LIST		*(*func)( PARSE *p, LOL *args, int *jmp ),
78	PARSE		*left,
79	PARSE		*right,
80	PARSE		*third,
81	const char 	*string,
82	const char 	*string1,
83	int		num )
84{
85	PARSE	*p = (PARSE *)malloc( sizeof( PARSE ) );
86
87	p->func = func;
88	p->left = left;
89	p->right = right;
90	p->third = third;
91	p->string = string;
92	p->string1 = string1;
93	p->num = num;
94	p->refs = 1;
95
96	return p;
97}
98
99void
100parse_refer( PARSE *p )
101{
102	++p->refs;
103}
104
105void
106parse_free( PARSE *p )
107{
108	if( --p->refs )
109	    return;
110
111	if( p->string )
112	    freestr( p->string );
113	if( p->string1 )
114	    freestr( p->string1 );
115	if( p->left )
116	    parse_free( p->left );
117	if( p->right )
118	    parse_free( p->right );
119	if( p->third )
120	    parse_free( p->third );
121
122	free( (char *)p );
123}
124