Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for %extra_argument #2

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 80 additions & 21 deletions lemon.c
Original file line number Diff line number Diff line change
Expand Up @@ -3622,6 +3622,81 @@ static void writeRuleText(FILE *out, struct rule *rp){
}
}

void replaceDefines(
struct lemon *lemp
){
FILE* out, * in;
int start,end,len;
char c;
char identifier[6];
char* vname;

in = file_open(lemp, ".go.tmp", "rb");
if (in == 0) {
return;
}
out = file_open(lemp, ".go", "wb");
if (out == 0) {
fclose(in);
return;
}

if (lemp->arg && lemp->arg[0]) {
// trim spaces
len = lemonStrlen(lemp->arg);
start = 0;
while (start < len && isspace(lemp->arg[start])) start++;

end = start+1;
while (end < len && !isspace(lemp->arg[end])) end++;

// allocate string for variable name and set its value
vname = (char*)malloc(end-start+1);
memcpy(vname, &lemp->arg[start], end-start);
vname[end-start] = 0;
}
else {
vname = NULL;
}

while (fread(&c, sizeof(c), 1, in) == 1) {
if (c == '@') {
// read identifier made of 5 characters
fread(&identifier, 1, 5, in);
identifier[5] = 0;

if (vname != NULL) {
if (strcmp(identifier, "SDECL") == 0) {
fprintf(out, "%s", lemp->arg);
}
else if (strcmp(identifier, "PDECL") == 0) {
fprintf(out, ",%s", lemp->arg);
}
else if (strcmp(identifier, "FETCH") == 0) {
fprintf(out, "%s := p.%s", vname, vname);
}
else if (strcmp(identifier, "FETC2") == 0) {
fprintf(out, "%s := yyp.%s", vname, vname);
}
else if (strcmp(identifier, "STORE") == 0) {
fprintf(out, "p.%s = %s", vname, vname);
}
}
}
else {
fwrite(&c, sizeof(c), 1, out);
}
}

if (vname != NULL) {
free(vname);
}

fclose(out);
fclose(in);

remove(file_makename(lemp, ".go.tmp"));
}

/* Generate C source code for the parser */
void ReportTable(
Expand All @@ -3643,7 +3718,7 @@ void ReportTable(

in = tplt_open(lemp);
if( in==0 ) return;
out = file_open(lemp,".go","wb");
out = file_open(lemp,".go.tmp","wb");
if( out==0 ){
fclose(in);
return;
Expand Down Expand Up @@ -3681,26 +3756,7 @@ void ReportTable(
fprintf(out,"const YYWILDCARD = %d\n",
lemp->wildcard ? lemp->wildcard->index : -1); lineno++;
print_stack_union(out,lemp,&lineno,mhflag);
name = lemp->name ? lemp->name : "Parse";
/*
if( lemp->arg && lemp->arg[0] ){
int i;
i = lemonStrlen(lemp->arg);
while( i>=1 && isspace(lemp->arg[i-1]) ) i--;
while( i>=1 && (isalnum(lemp->arg[i-1]) || lemp->arg[i-1]=='_') ) i--;
fprintf(out,"#define %sARG_SDECL %s;\n",name,lemp->arg); lineno++;
fprintf(out,"#define %sARG_PDECL ,%s\n",name,lemp->arg); lineno++;
fprintf(out,"#define %sARG_FETCH %s = yypParser->%s\n",
name,lemp->arg,&lemp->arg[i]); lineno++;
fprintf(out,"#define %sARG_STORE yypParser->%s = %s\n",
name,&lemp->arg[i],&lemp->arg[i]); lineno++;
}else{
fprintf(out,"#define %sARG_SDECL\n",name); lineno++;
fprintf(out,"#define %sARG_PDECL\n",name); lineno++;
fprintf(out,"#define %sARG_FETCH\n",name); lineno++;
fprintf(out,"#define %sARG_STORE\n",name); lineno++;
}
*/

fprintf(out,"const YYNSTATE = %d\n",lemp->nstate); lineno++;
fprintf(out,"const YYNRULE = %d\n",lemp->nrule); lineno++;
fprintf(out,"const YYERRORSYMBOL = %d\n",
Expand Down Expand Up @@ -4039,6 +4095,9 @@ void ReportTable(

fclose(in);
fclose(out);

replaceDefines(lemp);

return;
}

Expand Down
27 changes: 17 additions & 10 deletions lempar.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ type yyParser struct {

traceWriter io.Writer
tracePrompt string

@SDECL
}

/*
Expand Down Expand Up @@ -235,10 +237,11 @@ func NewParser() *yyParser {
** the value.
*/
func (p *yyParser) destructor(major YYCODETYPE, minor *YYMINORTYPE) {
// TODO(nsf): ParseARG_FETCH
@FETCH
switch major {
%%
}
@STORE
}

/*
Expand Down Expand Up @@ -367,7 +370,7 @@ func (p *yyParser) findReduceAction(stateno YYACTIONTYPE, lookahead YYCODETYPE)
** TODO(nsf): We have a dynamic stack, it can't overflow? remove this method?
*/
func (p *yyParser) stackOverflow(pminor *YYMINORTYPE) {
// TODO(nsf): ParseARG_FETCH
@FETCH
p.idx--
// TODO(nsf): add 'if debug' for dead code elimination
if p.traceWriter != nil {
Expand All @@ -378,7 +381,7 @@ func (p *yyParser) stackOverflow(pminor *YYMINORTYPE) {
p.popParserStack()
}
%%
// TODO(nsf): ParseARG_STORE
@STORE
}

/*
Expand Down Expand Up @@ -438,6 +441,8 @@ func (yyp *yyParser) reduce(ruleno YYACTIONTYPE) {
var yygotominor YYMINORTYPE
var yysize int

@FETC2

// TODO(nsf): add 'if debug' for dead code elimination
if yyp.traceWriter != nil && ruleno >= 0 && int(ruleno) < len(yyRuleName) {
fmt.Fprintf(yyp.traceWriter, "%sReduce [%s].\n",
Expand Down Expand Up @@ -480,7 +485,7 @@ func (yyp *yyParser) reduce(ruleno YYACTIONTYPE) {
** The following code executes when the parse fails
*/
func (p *yyParser) parseFailed() {
// TODO(nsf): ParseARG_FETCH
@FETCH

// TODO(nsf): add 'if debug' for dead code elimination
if p.traceWriter != nil {
Expand All @@ -491,25 +496,25 @@ func (p *yyParser) parseFailed() {
p.popParserStack()
}
%%
// TODO(nsf): ParseARG_STORE
@STORE
}

/*
** The following code executes when a syntax error first occurs.
*/
func (p *yyParser) syntaxError(major YYCODETYPE, minor YYMINORTYPE) {
// TODO(nsf): ParseARG_FETCH
@FETCH

// TODO(nsf): #define TOKEN (minor.yy0)
%%
// TODO(nsf): ParseARG_STORE
@STORE
}

/*
** The following is executed when the parser accepts
*/
func (p *yyParser) accept() {
// TODO(nsf): ParseARG_FETCH
@FETCH

// TODO(nsf): add 'if debug' for dead code elimination
if p.traceWriter != nil {
Expand All @@ -519,7 +524,7 @@ func (p *yyParser) accept() {
p.popParserStack()
}
%%
// TODO(nsf): ParseARG_STORE
@STORE
}

/* The main parser program.
Expand All @@ -541,14 +546,16 @@ func (p *yyParser) accept() {
** Outputs:
** None.
*/
func (p *yyParser) Parse(major YYCODETYPE, minor ParseTOKENTYPE, arg ...interface{}) {
func (p *yyParser) Parse(major YYCODETYPE, minor ParseTOKENTYPE @PDECL) {
var (
minorunion YYMINORTYPE
act YYACTIONTYPE
endofinput bool
errorhit bool
)

@STORE

if p.idx < 0 {
p.idx = 0
p.errcnt = -1
Expand Down