LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 03-28-2010, 12:23 PM   #136
MTK358
LQ 5k Club
 
Registered: Sep 2009
Posts: 6,443

Original Poster
Blog Entries: 3

Rep: Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723

So you have to define the types of non-terminals using %type, right?
 
Click here to see the post LQ members have rated as the most helpful post in this thread.
Old 03-28-2010, 12:41 PM   #137
MTK358
LQ 5k Club
 
Registered: Sep 2009
Posts: 6,443

Original Poster
Blog Entries: 3

Rep: Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723
That fixed it, but now I have another problem:

Code:
%union {
	char* string;
	Node* node;
}

%token <string> INTEGER
%token <string> IDENTIFIER

%type <node> expr
"Node" is a typedef'd struct that represents a node in the abstract syntax tree.

Code:
$ ./compile
Running YACC:
lang.y: conflicts: 4 shift/reduce
Running Lex:
Running GCC:
In file included from lang.l:2:
lang.y:12: error: expected specifier-qualifier-list before ‘Node’
GCC returned with exit code 1

Last edited by MTK358; 03-28-2010 at 12:43 PM.
 
Old 03-28-2010, 01:00 PM   #138
theNbomr
LQ 5k Club
 
Registered: Aug 2005
Distribution: OpenSuse, Fedora, Redhat, Debian
Posts: 5,399
Blog Entries: 2

Rep: Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908
I don't see anything wrong with the grammar part of the code, and it seems to be the compiler complaining, so how about showing the definition of the Node type. Is it in the code section of the yacc file, or is it in a header file? If the latter, is there a #include for it?

You seem to spend relatively little time tracking down problems on your own. It might be a helpful learning experience to dig into the problems a little more before posting for help. Just a friendly suggestion.

--- rod.
 
1 members found this post helpful.
Old 03-28-2010, 01:04 PM   #139
MTK358
LQ 5k Club
 
Registered: Sep 2009
Posts: 6,443

Original Poster
Blog Entries: 3

Rep: Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723
I don't know, the Node definition is in a separate .h file that is included in the .y file.

Anyway, this is it:

Code:
struct Node {
	int type;
	union {
		struct {
			int type;
			int numOps;
			struct Node** ops;
		} opValues;
		char* litValue;
		char* idValue;
	};
};
typedef struct Node Node;
 
Old 03-28-2010, 03:51 PM   #140
MTK358
LQ 5k Club
 
Registered: Sep 2009
Posts: 6,443

Original Poster
Blog Entries: 3

Rep: Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723
OK, I got that fixed now, but here I really got stuck:

Code:
Node *mkOpNode(int type, int numOps, /*Node*/ ...) {
	Node* n = malloc(sizeof(Node));
	n->type = NODE_OP;
	n->opValues.type = type;
	n->opValues.numOps = numOps;
	n->opValues.ops = malloc(sizeof(Node*)*numOps);
	if(numOps > 0 && n->opValues.ops == NULL) {
		fprintf(stderr, "error: cannot allocate memory for node\n");
		exit(1);
	}
	va_list ap;
	int i;
	for(i=0; i<numOps; i++) {
		n->opValues.ops[i] = va_arg(ap, Node*); // Segfault here!
	}
	va_end(ap);
	return n;
}
When it reaches the line highlighted in bold, it segfaults.

I used gdb and found that this happens on the first iteration, so it couldn't be going out the array's bounds. I also found that n->opValues.ops (which is of Node** type) is not NULL, so that isn't the problem. I wonder what's wrong?

Last edited by MTK358; 03-28-2010 at 03:53 PM.
 
Old 03-28-2010, 04:17 PM   #141
larryherman
LQ Newbie
 
Registered: Sep 2003
Distribution: RHEL, SUSE, SLED
Posts: 12

Rep: Reputation: 2
You didn't call va_start() before calling va_arg(), so ap has no initial value; if you try examining it in gdb you should see it's either NULL (0) or has some random (garbage) value.

It's good that you used gdb but when you have an error examining the values of all of the variables in the section of code in question may be necessary to figure out what's going on.
 
1 members found this post helpful.
Old 03-28-2010, 06:59 PM   #142
MTK358
LQ 5k Club
 
Registered: Sep 2009
Posts: 6,443

Original Poster
Blog Entries: 3

Rep: Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723
That's fixed, but this is really strange now:

Code:
$ ./lang
8 + 3
+
    Literal: 8 + 3

    Identifier: 8 + 3

    Literal: 3

    Identifier: 3
WTF?!?!?

It's supposed to look exactly like this:

Code:
8 + 3
+
    Literal: 8
    Literal: 3
 
Old 03-28-2010, 07:11 PM   #143
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by MTK358 View Post
That's fixed, but this is really strange now:

Code:
$ ./lang
8 + 3
+
    Literal: 8 + 3

    Identifier: 8 + 3

    Literal: 3

    Identifier: 3
WTF?!?!?

It's supposed to look exactly like this:

Code:
8 + 3
+
    Literal: 8
    Literal: 3
Well, I guess now it's the time:

Welcome to the wonderful world of LEX + YACC debugging .
 
Old 03-28-2010, 07:26 PM   #144
MTK358
LQ 5k Club
 
Registered: Sep 2009
Posts: 6,443

Original Poster
Blog Entries: 3

Rep: Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723
I fixed it!

The funny strings were because yylval was stored in the nodes, but it changes later during parsing. I solved that by making a simple function that allocates a duplicate string.

The Literal/Identifiers with the same value were because I for got the breaks in the switch statement that acted on different nodes.

Now the output is EXACTLY like my example.
 
Old 03-28-2010, 07:38 PM   #145
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by MTK358 View Post
I fixed it!

The funny strings were because yylval was stored in the nodes, but it changes later during parsing. I solved that by making a simple function that allocates a duplicate string.

The Literal/Identifiers with the same value were because I for got the breaks in the switch statement that acted on different nodes.

Now the output is EXACTLY like my example.
So, now you probably have some feeling of (lack of) variables locality, encapsulation and at all relationship between language constructs recognized by parser and triggered by recognition callbacks.
 
Old 03-28-2010, 08:05 PM   #146
MTK358
LQ 5k Club
 
Registered: Sep 2009
Posts: 6,443

Original Poster
Blog Entries: 3

Rep: Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723
Code:
stmt: This is line 44
	expr '\n' { $$ = $1; }
	IF expr '\n' stmts ';' '\n' { $$ = mkOpNode(IF, 2, $2, $4); }
;
Code:
$ ./compile 
Running YACC:
lang.y:45.21-22: $$ for the midrule at $3 of `stmt' has no declared type
lang.y:46.60-61: $2 of `stmt' has no declared type
lang.y:46.64-65: $4 of `stmt' has no declared type
YACC returned with exit code 1
What does this mean?
 
Old 03-28-2010, 09:05 PM   #147
larryherman
LQ Newbie
 
Registered: Sep 2003
Distribution: RHEL, SUSE, SLED
Posts: 12

Rep: Reputation: 2
Are you missing a vertical bar between the two lines of your stmt rule? (You want a stmt to be either an expr followed by a newline, or an if statement.)
 
Old 03-29-2010, 07:05 AM   #148
MTK358
LQ 5k Club
 
Registered: Sep 2009
Posts: 6,443

Original Poster
Blog Entries: 3

Rep: Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723
Garbled literals/identifiers again:

(input is highlighted in bold)

Code:
$ ./lang
if a = 0
        b := c + (4 * x)
;
if
  EQ
    Identifier: a =
    Literal: 0
  :=
    Identifier: b := c + (4 * x)

    +
      Identifier: c +
      *
        Literal: 4
        Identifier: x)
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
lex and yacc in RHEL4 birds Linux - Software 1 06-03-2009 02:56 AM
LEX and YACC with C gr33ndata Programming 4 11-18-2007 05:12 PM
Lex and Yacc on Federo 2.0 vivekian Fedora 6 05-20-2006 09:09 AM
Lex and Yacc on Mandrake 9.2.2 Anuradha Linux - Software 0 07-02-2005 03:32 AM
Lex & YACC coolfrog Programming 3 09-25-2004 07:00 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 05:11 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration