title: Why is this struct unknown at compile time?
body: <p>I am using <code>Ox</code>, <code>bison</code> and <code>lex</code> to write an attribute grammar. In my grammar, I use a symbol table to keep track of identifiers that are in scope.</p>
  <p>The symbol table struct is defined in a <code>parser.h</code> header:</p>
  <pre class="lang-c prettyprint-override"><code>struct st_;
  typedef struct st_
  {
      char** names;
      void** vals;
      char** types;
      int len;
      int maxlen;
  } ST;
  </code></pre>
  <p>Ox produces the files <code>oxout.tab.h</code> and <code>oxout.tab.c</code> which are the outputs of <code>bison</code> after checking the grammar.</p>
  <p>This is the head part of my <code>ox</code> file:</p>
  <pre class="lang-c prettyprint-override"><code>%{
  #include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;errno.h&gt;
  #include &lt;string.h&gt;
  #include &quot;parser.h&quot;
  
  int yylex(void);
  void yyerror(char *);
  extern int line_number;
  
  struct test {
      ST s;
  };
  
  ST add(ST table, char* name, void* val, char* type);
  ST addMaybe(ST table, char* name, void* val, char* type);
  ST addAll(ST old, ST new);
  ST init_st();
  bool containsT(ST table, char* name, char* type);
  bool contains(ST table, char* name);
  
  void oxerrorf(char* f, char* s);
  %}
  
  %start Start
  
  %token INTERFACE END CLASS IMPLEMENTS VAR METHOD INT RETURN IF THEN ELSE
  %token WHILE DO NOT AND NEW THIS _NULL EOC SCOL COL BRACL BRACR DOT COMMA 
  %token ASSIGNMENT PLUS ASTERISK MINUS LT EQ DEC HEX ID NEWLINE
  
  @attributes { ST st; } Program Interface Class MaybeIDs InterfaceContents
  @attributes { ST st; } Types Members Stats Negations Term Exprs Expr
  @attributes { ST st; } Additions Ands ArithOps MaybeElse
  @attributes { char* yystrval; } ID
  @attributes { ST st; char* name; } AbstractMethod Type Member Par Stat
  @attributes { ST st; ST stUp; } Pars 
  
  
  @traversal @preorder LRpre
  @traversal PV
  
  %%
  // definitions...
  </code></pre>
  <p>this is transformed to the following <code>oxout.tab.c</code>:</p>
  <pre class="lang-c prettyprint-override"><code>#include &lt;stdbool.h&gt;
  #include &lt;stdlib.h&gt;
  #if defined(__sun) &amp;&amp; defined(__SVR4)
  #include &lt;strings.h&gt;
  #else
  #include &lt;string.h&gt;
  #endif
  
  /* Identify Ox output. */
  #define YYYOX 1
  
  #line 1 &quot;littleparser.y&quot;
  
  #include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;errno.h&gt;
  #include &lt;string.h&gt;
  #include &quot;parser.h&quot;
  
  int yylex(void);
  void yyerror(char *);
  extern int line_number;
  
  struct test {
      ST s;
  };
  
  ST add(ST table, char* name, void* val, char* type);
  ST addMaybe(ST table, char* name, void* val, char* type);
  ST addAll(ST old, ST new);
  ST init_st();
  bool containsT(ST table, char* name, char* type);
  bool contains(ST table, char* name);
  
  void oxerrorf(char* f, char* s);
  #line 93 &quot;oxout.y&quot;
  
  struct yyyT1
  #line 42 &quot;littleparser.y&quot;
   { ST st; }
  #line 98 &quot;oxout.y&quot;
  ;
  
  struct yyyT2
  #line 43 &quot;littleparser.y&quot;
   { ST st; }
  #line 104 &quot;oxout.y&quot;
  ;
  
  struct yyyT3
  #line 44 &quot;littleparser.y&quot;
   { ST st; }
  #line 110 &quot;oxout.y&quot;
  ;
  
  struct yyyT4
  #line 45 &quot;littleparser.y&quot;
   { char* yystrval; }
  #line 116 &quot;oxout.y&quot;
  ;
  
  struct yyyT5
  #line 46 &quot;littleparser.y&quot;
   { ST st; char* name; }
  #line 122 &quot;oxout.y&quot;
  ;
  
  struct yyyT6
  #line 47 &quot;littleparser.y&quot;
   { ST st; ST stUp; }
  #line 128 &quot;oxout.y&quot;
  ;
  </code></pre>
  <p>Now when I compile this using</p>
  <pre class="lang-sh prettyprint-override"><code>&gt; gcc  parser.h oxout.tab.h lex.yy.c oxout.tab.c -o ag
  </code></pre>
  <p><code>gcc</code> throws me the most curious error:</p>
  <pre class="lang-sh prettyprint-override"><code>littleparser.y:42:4: error: unknown type name ‘ST’
     42 | @attributes { ST st; } Program Interface Class MaybeIDs InterfaceContents
        |    ^~
  littleparser.y:43:4: error: unknown type name ‘ST’
     43 | @attributes { ST st; } Types Members Stats Negations Term Exprs Expr
        |    ^~
  littleparser.y:44:4: error: unknown type name ‘ST’
     44 | @attributes { ST st; } Additions Ands ArithOps MaybeElse
        |    ^~
  littleparser.y:46:4: error: unknown type name ‘ST’
     46 | @attributes { ST st; char* name; } AbstractMethod Type Member Par Stat
        |    ^~
  littleparser.y:47:4: error: unknown type name ‘ST’
     47 | @attributes { ST st; ST stUp; } Pars
        |    ^~
  littleparser.y:47:11: error: unknown type name ‘ST’
     47 | @attributes { ST st; ST stUp; } Pars
        |           ^~
  </code></pre>
  <p>The interesting this is this:</p>
  <pre class="lang-c prettyprint-override"><code>struct test {
      ST s;
  };
  
  ST add(ST table, char* name, void* val, char* type);
  // and the other declarations
  </code></pre>
  <p>seem to compile fine;</p>
  <p>however</p>
  <pre class="lang-c prettyprint-override"><code>struct yyyT1
  #line 42 &quot;littleparser.y&quot;
   { ST st; }
  #line 98 &quot;oxout.y&quot;
  ;
  </code></pre>
  <p>throws the unknown type name error.</p>
  <p>Why is that?
  All these definitions seem to be in scope/defined at the time it is compiled. (Also when I look at the output of the preprocessor the contents of <code>parser.h</code> are inlined before their first usage.)</p>
  <p>I am not extremely savvy with <code>C</code> so I have probably missed something quite obvious I guess.
  Sadly <a href="https://stackoverflow.com/questions/13634495/c-typedef-incomplete-type">C Typedef - Incomplete Type</a> did not help me finding the error;</p>
  <p>I tried to define the struct inside the <code>c</code> file, move the <code>typedef</code> somewhere else, keeping it all in the <code>h</code> file, but nothing seems to work.</p>
  <p>Where am I going wrong here?</p>