BsParserFX.y 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  1. %{
  2. #include "BsParserFX.h"
  3. #include "BsLexerFX.h"
  4. #define inline
  5. void yyerror(YYLTYPE *locp, ParseState* parse_state, yyscan_t scanner, const char *msg);
  6. %}
  7. %code requires{
  8. #include "BsMMAlloc.h"
  9. #include "BsASTFX.h"
  10. #include "BsIncludeHandler.h"
  11. #ifndef YY_TYPEDEF_YY_SCANNER_T
  12. #define YY_TYPEDEF_YY_SCANNER_T
  13. typedef void* yyscan_t;
  14. #endif
  15. typedef struct YYLTYPE {
  16. int first_line;
  17. int first_column;
  18. int last_line;
  19. int last_column;
  20. char *filename;
  21. } YYLTYPE;
  22. #define YYLTYPE_IS_DECLARED 1
  23. #define YYLLOC_DEFAULT(Current, Rhs, N) \
  24. do \
  25. if (N) \
  26. { \
  27. (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
  28. (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
  29. (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
  30. (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
  31. (Current).filename = YYRHSLOC (Rhs, 1).filename; \
  32. } \
  33. else \
  34. { \
  35. (Current).first_line = (Current).last_line = YYRHSLOC (Rhs, 0).last_line; \
  36. (Current).first_column = (Current).last_column = YYRHSLOC (Rhs, 0).last_column; \
  37. (Current).filename = NULL; \
  38. } \
  39. while (0)
  40. }
  41. %output "BsParserFX.c"
  42. %defines "BsParserFX.h"
  43. %define api.pure
  44. %locations
  45. %lex-param { yyscan_t scanner }
  46. %parse-param { ParseState* parse_state }
  47. %parse-param { yyscan_t scanner }
  48. %glr-parser
  49. %union {
  50. int intValue;
  51. float floatValue;
  52. float matrixValue[16];
  53. int intVectorValue[4];
  54. const char* strValue;
  55. ASTFXNode* nodePtr;
  56. NodeOption nodeOption;
  57. }
  58. /* Value types */
  59. %token <intValue> TOKEN_INTEGER
  60. %token <floatValue> TOKEN_FLOAT
  61. %token <intValue> TOKEN_BOOLEAN
  62. %token <strValue> TOKEN_STRING
  63. %token <strValue> TOKEN_IDENTIFIER
  64. /* State value types */
  65. %token <intValue> TOKEN_FILLMODEVALUE
  66. %token <intValue> TOKEN_CULLANDQUEUEVALUE
  67. %token <intValue> TOKEN_COMPFUNCVALUE
  68. %token <intValue> TOKEN_OPVALUE
  69. %token <intValue> TOKEN_BLENDOPVALUE
  70. %token <intValue> TOKEN_COLORMASK
  71. /* Shader keywords */
  72. %token TOKEN_OPTIONS TOKEN_TECHNIQUE TOKEN_MIXIN
  73. /* Options keywords */
  74. %token TOKEN_SEPARABLE TOKEN_SORT TOKEN_PRIORITY TOKEN_TRANSPARENT
  75. /* Technique keywords */
  76. %token TOKEN_RENDERER TOKEN_PASS TOKEN_TAGS
  77. /* Pass keywords */
  78. %token TOKEN_CODE TOKEN_BLEND TOKEN_RASTER TOKEN_DEPTH TOKEN_STENCIL
  79. /* Rasterizer state keywords */
  80. %token TOKEN_FILLMODE TOKEN_CULLMODE TOKEN_DEPTHBIAS TOKEN_SDEPTHBIAS
  81. %token TOKEN_DEPTHCLIP TOKEN_SCISSOR TOKEN_MULTISAMPLE TOKEN_AALINE
  82. /* Depth state keywords */
  83. %token TOKEN_DEPTHREAD TOKEN_DEPTHWRITE TOKEN_COMPAREFUNC
  84. /* Stencil state keywords */
  85. %token TOKEN_STENCILREF TOKEN_ENABLED TOKEN_READMASK TOKEN_WRITEMASK
  86. %token TOKEN_STENCILOPFRONT TOKEN_STENCILOPBACK TOKEN_FAIL TOKEN_ZFAIL
  87. /* Blend state keywords */
  88. %token TOKEN_ALPHATOCOVERAGE TOKEN_INDEPENDANTBLEND TOKEN_TARGET TOKEN_INDEX
  89. %token TOKEN_COLOR TOKEN_ALPHA TOKEN_SOURCE TOKEN_DEST TOKEN_OP
  90. %type <nodePtr> shader;
  91. %type <nodeOption> shader_statement;
  92. %type <nodePtr> options;
  93. %type <nodePtr> options_header;
  94. %type <nodeOption> options_option;
  95. %type <nodePtr> technique;
  96. %type <nodePtr> technique_header;
  97. %type <nodeOption> technique_statement;
  98. %type <nodeOption> technique_option;
  99. %type <nodePtr> tags;
  100. %type <nodePtr> tags_header;
  101. %type <nodePtr> pass;
  102. %type <nodePtr> pass_header;
  103. %type <nodeOption> pass_statement;
  104. %type <nodeOption> pass_option;
  105. %type <nodePtr> raster;
  106. %type <nodePtr> raster_header;
  107. %type <nodeOption> raster_option;
  108. %type <nodePtr> depth;
  109. %type <nodePtr> depth_header;
  110. %type <nodeOption> depth_option;
  111. %type <nodePtr> stencil;
  112. %type <nodePtr> stencil_header;
  113. %type <nodeOption> stencil_option;
  114. %type <nodePtr> blend;
  115. %type <nodePtr> blend_header;
  116. %type <nodeOption> blend_option;
  117. %type <nodePtr> code;
  118. %type <nodePtr> code_header;
  119. %type <nodePtr> stencil_op_front_header;
  120. %type <nodePtr> stencil_op_back_header;
  121. %type <nodeOption> stencil_op_option;
  122. %type <nodePtr> target;
  123. %type <nodePtr> target_header;
  124. %type <nodeOption> target_option;
  125. %type <nodePtr> blend_color_header;
  126. %type <nodePtr> blend_alpha_header;
  127. %type <nodeOption> blenddef_option;
  128. %%
  129. /* Shader */
  130. shader
  131. : /* empty */ { }
  132. | shader_statement shader { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &$1); }
  133. ;
  134. shader_statement
  135. : options { $$.type = OT_Options; $$.value.nodePtr = $1; }
  136. | technique { $$.type = OT_Technique; $$.value.nodePtr = $1; }
  137. ;
  138. /* Options */
  139. options
  140. : options_header '{' options_body '}' ';' { nodePop(parse_state); $$ = $1; }
  141. ;
  142. options_header
  143. : TOKEN_OPTIONS
  144. {
  145. $$ = nodeCreate(parse_state->memContext, NT_Options);
  146. nodePush(parse_state, $$);
  147. }
  148. ;
  149. options_body
  150. : /* empty */
  151. | options_option options_body { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &$1); }
  152. ;
  153. options_option
  154. : TOKEN_SEPARABLE '=' TOKEN_BOOLEAN ';' { $$.type = OT_Separable; $$.value.intValue = $3; }
  155. | TOKEN_SORT '=' TOKEN_CULLANDQUEUEVALUE ';' { $$.type = OT_Sort; $$.value.intValue = $3; }
  156. | TOKEN_PRIORITY '=' TOKEN_INTEGER ';' { $$.type = OT_Priority; $$.value.intValue = $3; }
  157. | TOKEN_TRANSPARENT '=' TOKEN_BOOLEAN ';' { $$.type = OT_Transparent; $$.value.intValue = $3; }
  158. ;
  159. /* Technique */
  160. technique
  161. : technique_header '{' technique_body '}' ';' { nodePop(parse_state); $$ = $1; }
  162. ;
  163. technique_header
  164. : TOKEN_TECHNIQUE TOKEN_IDENTIFIER
  165. {
  166. $$ = nodeCreate(parse_state->memContext, NT_Technique);
  167. nodePush(parse_state, $$);
  168. NodeOption entry; entry.type = OT_Identifier; entry.value.strValue = $2;
  169. nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &entry);
  170. }
  171. | TOKEN_MIXIN TOKEN_IDENTIFIER
  172. {
  173. $$ = nodeCreate(parse_state->memContext, NT_Mixin);
  174. nodePush(parse_state, $$);
  175. NodeOption entry; entry.type = OT_Identifier; entry.value.strValue = $2;
  176. nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &entry);
  177. }
  178. ;
  179. technique_body
  180. : /* empty */
  181. | technique_statement technique_body { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &$1); }
  182. ;
  183. technique_statement
  184. : technique_option
  185. | pass { $$.type = OT_Pass; $$.value.nodePtr = $1; }
  186. | pass_option
  187. | code { $$.type = OT_Code; $$.value.nodePtr = $1; }
  188. ;
  189. technique_option
  190. : TOKEN_RENDERER '=' TOKEN_STRING ';' { $$.type = OT_Renderer; $$.value.strValue = $3; }
  191. | TOKEN_MIXIN TOKEN_IDENTIFIER ';' { $$.type = OT_Mixin; $$.value.strValue = $2; }
  192. | tags { $$.type = OT_Tags; $$.value.nodePtr = $1; }
  193. ;
  194. /* Technique tags */
  195. tags
  196. : tags_header '{' tags_body '}' ';' { nodePop(parse_state); $$ = $1; }
  197. ;
  198. tags_header
  199. : TOKEN_TAGS '='
  200. {
  201. $$ = nodeCreate(parse_state->memContext, NT_Tags);
  202. nodePush(parse_state, $$);
  203. }
  204. ;
  205. tags_body
  206. : /* empty */
  207. | TOKEN_STRING
  208. {
  209. NodeOption entry; entry.type = OT_TagValue; entry.value.strValue = $1;
  210. nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &entry);
  211. }
  212. | TOKEN_STRING ',' tags_body
  213. {
  214. NodeOption entry; entry.type = OT_TagValue; entry.value.strValue = $1;
  215. nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &entry);
  216. }
  217. ;
  218. /* Pass */
  219. pass
  220. : pass_header '{' pass_body '}' ';' { nodePop(parse_state); $$ = $1; }
  221. ;
  222. pass_header
  223. : TOKEN_PASS
  224. {
  225. $$ = nodeCreate(parse_state->memContext, NT_Pass);
  226. nodePush(parse_state, $$);
  227. }
  228. ;
  229. pass_body
  230. : /* empty */
  231. | pass_statement pass_body { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &$1); }
  232. ;
  233. pass_statement
  234. : pass_option
  235. | code { $$.type = OT_Code; $$.value.nodePtr = $1; }
  236. ;
  237. pass_option
  238. : raster { $$.type = OT_Raster; $$.value.nodePtr = $1; }
  239. | depth { $$.type = OT_Depth; $$.value.nodePtr = $1; }
  240. | stencil { $$.type = OT_Stencil; $$.value.nodePtr = $1; }
  241. | blend { $$.type = OT_Blend; $$.value.nodePtr = $1; }
  242. ;
  243. /* Raster state */
  244. raster
  245. : raster_header '{' raster_body '}' ';' { nodePop(parse_state); $$ = $1; }
  246. ;
  247. raster_header
  248. : TOKEN_RASTER
  249. {
  250. $$ = nodeCreate(parse_state->memContext, NT_Raster);
  251. nodePush(parse_state, $$);
  252. }
  253. ;
  254. raster_body
  255. : /* empty */
  256. | raster_option raster_body { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &$1); }
  257. ;
  258. raster_option
  259. : TOKEN_FILLMODE '=' TOKEN_FILLMODEVALUE ';' { $$.type = OT_FillMode; $$.value.intValue = $3; }
  260. | TOKEN_CULLMODE '=' TOKEN_CULLANDQUEUEVALUE ';' { $$.type = OT_CullMode; $$.value.intValue = $3; }
  261. | TOKEN_SCISSOR '=' TOKEN_BOOLEAN ';' { $$.type = OT_Scissor; $$.value.intValue = $3; }
  262. | TOKEN_MULTISAMPLE '=' TOKEN_BOOLEAN ';' { $$.type = OT_Multisample; $$.value.intValue = $3; }
  263. | TOKEN_AALINE '=' TOKEN_BOOLEAN ';' { $$.type = OT_AALine; $$.value.intValue = $3; }
  264. ;
  265. /* Depth state */
  266. depth
  267. : depth_header '{' depth_body '}' ';' { nodePop(parse_state); $$ = $1; }
  268. ;
  269. depth_header
  270. : TOKEN_DEPTH
  271. {
  272. $$ = nodeCreate(parse_state->memContext, NT_Depth);
  273. nodePush(parse_state, $$);
  274. }
  275. ;
  276. depth_body
  277. : /* empty */
  278. | depth_option depth_body { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &$1); }
  279. ;
  280. depth_option
  281. : TOKEN_DEPTHREAD '=' TOKEN_BOOLEAN ';' { $$.type = OT_DepthRead; $$.value.intValue = $3; }
  282. | TOKEN_DEPTHWRITE '=' TOKEN_BOOLEAN ';' { $$.type = OT_DepthWrite; $$.value.intValue = $3; }
  283. | TOKEN_COMPAREFUNC '=' TOKEN_COMPFUNCVALUE ';' { $$.type = OT_CompareFunc; $$.value.intValue = $3; }
  284. | TOKEN_DEPTHBIAS '=' TOKEN_FLOAT ';' { $$.type = OT_DepthBias; $$.value.floatValue = $3; }
  285. | TOKEN_SDEPTHBIAS '=' TOKEN_FLOAT ';' { $$.type = OT_SDepthBias; $$.value.floatValue = $3; }
  286. | TOKEN_DEPTHCLIP '=' TOKEN_BOOLEAN ';' { $$.type = OT_DepthClip; $$.value.intValue = $3; }
  287. ;
  288. /* Stencil state */
  289. stencil
  290. : stencil_header '{' stencil_body '}' ';' { nodePop(parse_state); $$ = $1; }
  291. ;
  292. stencil_header
  293. : TOKEN_STENCIL
  294. {
  295. $$ = nodeCreate(parse_state->memContext, NT_Stencil);
  296. nodePush(parse_state, $$);
  297. }
  298. ;
  299. stencil_body
  300. : /* empty */
  301. | stencil_option stencil_body { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &$1); }
  302. ;
  303. stencil_option
  304. : TOKEN_ENABLED '=' TOKEN_BOOLEAN ';' { $$.type = OT_Enabled; $$.value.intValue = $3; }
  305. | TOKEN_READMASK '=' TOKEN_INTEGER ';' { $$.type = OT_StencilReadMask; $$.value.intValue = $3; }
  306. | TOKEN_WRITEMASK '=' TOKEN_INTEGER ';' { $$.type = OT_StencilWriteMask; $$.value.intValue = $3; }
  307. | stencil_op_front_header '{' stencil_op_body '}' ';' { nodePop(parse_state); $$.type = OT_StencilOpFront; $$.value.nodePtr = $1; }
  308. | stencil_op_back_header '{' stencil_op_body '}' ';' { nodePop(parse_state); $$.type = OT_StencilOpBack; $$.value.nodePtr = $1; }
  309. | stencil_op_front_header '{' stencil_op_body_init '}' ';' { nodePop(parse_state); $$.type = OT_StencilOpFront; $$.value.nodePtr = $1; }
  310. | stencil_op_back_header '{' stencil_op_body_init '}' ';' { nodePop(parse_state); $$.type = OT_StencilOpBack; $$.value.nodePtr = $1; }
  311. | TOKEN_STENCILREF '=' TOKEN_INTEGER ';' { $$.type = OT_StencilRef; $$.value.intValue = $3; }
  312. ;
  313. /* Blend state */
  314. blend
  315. : blend_header '{' blend_body '}' ';' { nodePop(parse_state); $$ = $1; }
  316. ;
  317. blend_header
  318. : TOKEN_BLEND
  319. {
  320. $$ = nodeCreate(parse_state->memContext, NT_Blend);
  321. nodePush(parse_state, $$);
  322. }
  323. ;
  324. blend_body
  325. : /* empty */
  326. | blend_option blend_body { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &$1); }
  327. ;
  328. blend_option
  329. : TOKEN_ALPHATOCOVERAGE '=' TOKEN_BOOLEAN ';' { $$.type = OT_AlphaToCoverage; $$.value.intValue = $3; }
  330. | TOKEN_INDEPENDANTBLEND '=' TOKEN_BOOLEAN ';' { $$.type = OT_IndependantBlend; $$.value.intValue = $3; }
  331. | target { $$.type = OT_Target; $$.value.nodePtr = $1; }
  332. ;
  333. /* Code blocks */
  334. code
  335. : code_header '{' TOKEN_INDEX '=' TOKEN_INTEGER ';' '}' ';'
  336. {
  337. NodeOption index;
  338. index.type = OT_Index;
  339. index.value.intValue = $5;
  340. nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &index);
  341. nodePop(parse_state);
  342. $$ = $1;
  343. }
  344. ;
  345. code_header
  346. : TOKEN_CODE
  347. {
  348. $$ = nodeCreate(parse_state->memContext, NT_Code);
  349. nodePush(parse_state, $$);
  350. }
  351. ;
  352. /* Stencil op */
  353. stencil_op_front_header
  354. : TOKEN_STENCILOPFRONT '='
  355. {
  356. $$ = nodeCreate(parse_state->memContext, NT_StencilOp);
  357. nodePush(parse_state, $$);
  358. }
  359. ;
  360. stencil_op_back_header
  361. : TOKEN_STENCILOPBACK '='
  362. {
  363. $$ = nodeCreate(parse_state->memContext, NT_StencilOp);
  364. nodePush(parse_state, $$);
  365. }
  366. ;
  367. stencil_op_body_init
  368. : TOKEN_OPVALUE ',' TOKEN_OPVALUE ',' TOKEN_OPVALUE ',' TOKEN_COMPFUNCVALUE
  369. {
  370. NodeOption fail; fail.type = OT_Fail; fail.value.intValue = $1;
  371. NodeOption zfail; zfail.type = OT_ZFail; zfail.value.intValue = $3;
  372. NodeOption pass; pass.type = OT_PassOp; pass.value.intValue = $5;
  373. NodeOption cmp; cmp.type = OT_CompareFunc; cmp.value.intValue = $7;
  374. nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &fail);
  375. nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &zfail);
  376. nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &pass);
  377. nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &cmp);
  378. }
  379. ;
  380. stencil_op_body
  381. : /* empty */
  382. | stencil_op_option stencil_op_body { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &$1); }
  383. ;
  384. stencil_op_option
  385. : TOKEN_FAIL '=' TOKEN_OPVALUE ';' { $$.type = OT_Fail; $$.value.intValue = $3; }
  386. | TOKEN_ZFAIL '=' TOKEN_OPVALUE ';' { $$.type = OT_ZFail; $$.value.intValue = $3; }
  387. | TOKEN_PASS '=' TOKEN_OPVALUE ';' { $$.type = OT_PassOp; $$.value.intValue = $3; }
  388. | TOKEN_COMPAREFUNC '=' TOKEN_COMPFUNCVALUE ';' { $$.type = OT_CompareFunc; $$.value.intValue = $3; }
  389. ;
  390. /* Target */
  391. target
  392. : target_header '{' target_body '}' ';' { nodePop(parse_state); $$ = $1; }
  393. ;
  394. target_header
  395. : TOKEN_TARGET
  396. {
  397. $$ = nodeCreate(parse_state->memContext, NT_Target);
  398. nodePush(parse_state, $$);
  399. }
  400. ;
  401. target_body
  402. : /* empty */
  403. | target_option target_body { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &$1); }
  404. ;
  405. target_option
  406. : TOKEN_INDEX '=' TOKEN_INTEGER ';' { $$.type = OT_Index; $$.value.intValue = $3; }
  407. | TOKEN_ENABLED '=' TOKEN_BOOLEAN ';' { $$.type = OT_Enabled; $$.value.intValue = $3; }
  408. | blend_color_header '{' blenddef_body '}' ';' { nodePop(parse_state); $$.type = OT_Color; $$.value.nodePtr = $1; }
  409. | blend_alpha_header '{' blenddef_body '}' ';' { nodePop(parse_state); $$.type = OT_Alpha; $$.value.nodePtr = $1; }
  410. | blend_color_header '{' blenddef_body_init '}' ';' { nodePop(parse_state); $$.type = OT_Color; $$.value.nodePtr = $1; }
  411. | blend_alpha_header '{' blenddef_body_init '}' ';' { nodePop(parse_state); $$.type = OT_Alpha; $$.value.nodePtr = $1; }
  412. | TOKEN_WRITEMASK '=' TOKEN_COLORMASK ';' { $$.type = OT_WriteMask; $$.value.intValue = $3; }
  413. ;
  414. /* Blend definition */
  415. blend_color_header
  416. : TOKEN_COLOR '='
  417. {
  418. $$ = nodeCreate(parse_state->memContext, NT_BlendDef);
  419. nodePush(parse_state, $$);
  420. }
  421. ;
  422. blend_alpha_header
  423. : TOKEN_ALPHA '='
  424. {
  425. $$ = nodeCreate(parse_state->memContext, NT_BlendDef);
  426. nodePush(parse_state, $$);
  427. }
  428. ;
  429. blenddef_body
  430. : /* empty */
  431. | blenddef_option blenddef_body { nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &$1); }
  432. ;
  433. blenddef_body_init
  434. : TOKEN_OPVALUE ',' TOKEN_OPVALUE ',' TOKEN_BLENDOPVALUE
  435. {
  436. NodeOption src; src.type = OT_Source; src.value.intValue = $1;
  437. NodeOption dst; dst.type = OT_Dest; dst.value.intValue = $3;
  438. NodeOption op; op.type = OT_Op; op.value.intValue = $5;
  439. nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &src);
  440. nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &dst);
  441. nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &op);
  442. }
  443. ;
  444. blenddef_option
  445. : TOKEN_SOURCE '=' TOKEN_OPVALUE ';' { $$.type = OT_Source; $$.value.intValue = $3; }
  446. | TOKEN_DEST '=' TOKEN_OPVALUE ';' { $$.type = OT_Dest; $$.value.intValue = $3; }
  447. | TOKEN_OP '=' TOKEN_BLENDOPVALUE ';' { $$.type = OT_Op; $$.value.intValue = $3; }
  448. ;
  449. %%
  450. void yyerror(YYLTYPE *locp, ParseState* parse_state, yyscan_t scanner, const char *msg)
  451. {
  452. parse_state->hasError = 1;
  453. parse_state->errorLine = locp->first_line;
  454. parse_state->errorColumn = locp->first_column;
  455. parse_state->errorMessage = mmalloc_strdup(parse_state->memContext, msg);
  456. parse_state->errorFile = locp->filename;
  457. }