ShaderFrog / glsl-parser

A GLSL ES 1.0 and 3.0 parser that can preserve whitespace and comments
https://shaderfrog.com
108 stars 9 forks source link

parser.parse fails on struct with #ifdef #36

Closed yorkie closed 2 hours ago

yorkie commented 2 hours ago

The parse() seems to fail a struct with preprocessor just like #ifdef:

import { parser } from '@shaderfrog/glsl-parser';

let source = `
struct Foo {
  vec3 pos;
#ifdef USE_FOLLOW
  vec3 follow;
#endif
};
`;
try {
  parser.parse(source);
} catch (err) {
  console.warn(err.format([{ text: source }]));
}

The error:

Error: Expected function prototype, function prototype scope, precision statement, prepocessor, or whitespace but "s" found.
 --> undefined:2:1
  |
2 | struct Foo {
  | ^
AndrewRayCode commented 2 hours ago

You need to preprocess the source string first! https://github.com/ShaderFrog/glsl-parser?tab=readme-ov-file#preprocessing

yorkie commented 2 hours ago

@AndrewRayCode Thank you for this reply, unfortunately preprocess doesn't work for my usecase, I wanna modify the glsl AST and generate the source that should include the preprocessors.

yorkie commented 2 hours ago

And at https://github.com/ShaderFrog/glsl-parser/blob/main/src/parser/glsl-grammar.pegjs#L1175:

statement_list = (statement / preprocessor)+

The glsl parser supports the preprocessors in statement list and others, but not getting considered at some like struct_declaration_list.

AndrewRayCode commented 2 hours ago

@yorkie That use case unfortunately is not supported by the parser.

Technically no preprocessor statements are valid GLSL. A program source code string should be fully preprocessed before being handed off to the parser. The official grammar (page 222) does not support preprocessor lines:

statement_list : statement statement_list statement

I think my intention of including a preprocessor line in this GLSL grammar was so that you can avoid preprocessing some programs, if you want, if they only contain top level preprocessor lines. I think it would be too complicated in the peg grammar to try to support arbitrary preprocessor lines in arbitrary places. If I were to make any feature change I think it makes more sense to remove the preprocessor line from the parser peg grammar.

yorkie commented 1 hour ago

@AndrewRayCode I see! Thank you for this explanation, in short, thanks a lot!