123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920 |
- /*
- +----------------------------------------------------------------------+
- | Copyright (c) The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | https://www.php.net/license/3_01.txt |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
- | Author: Dmitry Stogov <dmitry@zend.com> |
- +----------------------------------------------------------------------+
- */
- /*
- To generate ffi_parser.c use llk <https://github.com/dstogov/llk>:
- php llk.php ffi.g
- */
- %start declarations
- %sub-start type_name
- %case-sensetive true
- %global-vars false
- %output "ffi_parser.c"
- %language "c"
- %indent "\t"
- %{
- /*
- +----------------------------------------------------------------------+
- | Copyright (c) The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | https://www.php.net/license/3_01.txt |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
- | Author: Dmitry Stogov <dmitry@zend.com> |
- +----------------------------------------------------------------------+
- */
- #ifdef HAVE_CONFIG_H
- # include "config.h"
- #endif
- #include "php.h"
- #include "php_ffi.h"
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #define yy_buf FFI_G(buf)
- #define yy_end FFI_G(end)
- #define yy_pos FFI_G(pos)
- #define yy_text FFI_G(text)
- #define yy_line FFI_G(line)
- /* forward declarations */
- static void yy_error(const char *msg);
- static void yy_error_sym(const char *msg, int sym);
- %}
- declarations:
- (
- {zend_ffi_dcl common_dcl = ZEND_FFI_ATTR_INIT;}
- "__extension__"?
- declaration_specifiers(&common_dcl)
- (
- {const char *name;}
- {size_t name_len;}
- {zend_ffi_dcl dcl;}
- {dcl = common_dcl;}
- declarator(&dcl, &name, &name_len)
- (
- {zend_ffi_val asm_str;}
- "__asm__"
- "("
- STRING(&asm_str)+
- /*TODO*/
- ")"
- )?
- attributes(&dcl)?
- initializer?
- {zend_ffi_declare(name, name_len, &dcl);}
- ( ","
- {dcl = common_dcl;}
- declarator(&dcl, &name, &name_len)
- attributes(&dcl)?
- initializer?
- {zend_ffi_declare(name, name_len, &dcl);}
- )*
- )?
- ";"
- )*
- ;
- declaration_specifiers(zend_ffi_dcl *dcl):
- ( ?{sym != YY_ID || !(dcl->flags & ZEND_FFI_DCL_TYPE_SPECIFIERS)}
- ( {if (dcl->flags & ZEND_FFI_DCL_STORAGE_CLASS) yy_error_sym("unexpected", sym);}
- "typedef"
- {dcl->flags |= ZEND_FFI_DCL_TYPEDEF;}
- | {if (dcl->flags & ZEND_FFI_DCL_STORAGE_CLASS) yy_error_sym("unexpected", sym);}
- "extern"
- {dcl->flags |= ZEND_FFI_DCL_EXTERN;}
- | {if (dcl->flags & ZEND_FFI_DCL_STORAGE_CLASS) yy_error_sym("unexpected", sym);}
- "static"
- {dcl->flags |= ZEND_FFI_DCL_STATIC;}
- | {if (dcl->flags & ZEND_FFI_DCL_STORAGE_CLASS) yy_error_sym("unexpected", sym);}
- "auto"
- {dcl->flags |= ZEND_FFI_DCL_AUTO;}
- | {if (dcl->flags & ZEND_FFI_DCL_STORAGE_CLASS) yy_error_sym("unexpected", sym);}
- "register"
- {dcl->flags |= ZEND_FFI_DCL_REGISTER;}
- // | "_Thread_local" // TODO: not-implemented ???
- | ("inline"|"__inline"|"__inline__")
- {dcl->flags |= ZEND_FFI_DCL_INLINE;}
- | "_Noreturn"
- {dcl->flags |= ZEND_FFI_DCL_NO_RETURN;}
- | "_Alignas"
- "("
- ( &type_name_start
- {zend_ffi_dcl align_dcl = ZEND_FFI_ATTR_INIT;}
- type_name(&align_dcl)
- {zend_ffi_align_as_type(dcl, &align_dcl);}
- | {zend_ffi_val align_val;}
- constant_expression(&align_val)
- {zend_ffi_align_as_val(dcl, &align_val);}
- )
- ")"
- | attributes(dcl)
- | type_qualifier(dcl)
- | type_specifier(dcl)
- )
- )+
- ;
- specifier_qualifier_list(zend_ffi_dcl *dcl):
- "__extension__"?
- ( ?{sym != YY_ID || zend_ffi_is_typedef_name((const char*)yy_text, yy_pos - yy_text) || (dcl->flags & ZEND_FFI_DCL_TYPE_SPECIFIERS) == 0}
- ( type_specifier(dcl)
- | type_qualifier(dcl)
- | attributes(dcl)
- )
- )+
- ;
- type_qualifier_list(zend_ffi_dcl *dcl):
- ( type_qualifier(dcl)
- | attributes(dcl)
- )+
- ;
- type_qualifier(zend_ffi_dcl *dcl):
- ("const"|"__const"|"__const__")
- {dcl->flags |= ZEND_FFI_DCL_CONST;}
- {dcl->attr |= ZEND_FFI_ATTR_CONST;}
- | ("restrict"|"__restrict"|"__restrict__")
- {dcl->flags |= ZEND_FFI_DCL_RESTRICT;}
- | ("volatile"|"__volatile"|"__volatile__")
- {dcl->flags |= ZEND_FFI_DCL_VOLATILE;}
- | "_Atomic"
- {dcl->flags |= ZEND_FFI_DCL_ATOMIC;}
- ;
- type_specifier(zend_ffi_dcl *dcl):
- {const char *name;}
- {size_t name_len;}
- ( {if (dcl->flags & ZEND_FFI_DCL_TYPE_SPECIFIERS) yy_error_sym("unexpected", sym);}
- "void"
- {dcl->flags |= ZEND_FFI_DCL_VOID;}
- | {if (dcl->flags & (ZEND_FFI_DCL_TYPE_SPECIFIERS-(ZEND_FFI_DCL_SIGNED|ZEND_FFI_DCL_UNSIGNED))) yy_error_sym("unexpected", sym);}
- "char"
- {dcl->flags |= ZEND_FFI_DCL_CHAR;}
- | {if (dcl->flags & (ZEND_FFI_DCL_TYPE_SPECIFIERS-(ZEND_FFI_DCL_SIGNED|ZEND_FFI_DCL_UNSIGNED|ZEND_FFI_DCL_INT))) yy_error_sym("unexpected", sym);}
- "short"
- {dcl->flags |= ZEND_FFI_DCL_SHORT;}
- | {if (dcl->flags & (ZEND_FFI_DCL_TYPE_SPECIFIERS-(ZEND_FFI_DCL_SIGNED|ZEND_FFI_DCL_UNSIGNED|ZEND_FFI_DCL_SHORT|ZEND_FFI_DCL_LONG|ZEND_FFI_DCL_LONG_LONG))) yy_error_sym("unexpected", sym);}
- "int"
- {dcl->flags |= ZEND_FFI_DCL_INT;}
- | {
- if (dcl->flags & ZEND_FFI_DCL_LONG) {
- if (dcl->flags & (ZEND_FFI_DCL_TYPE_SPECIFIERS-(ZEND_FFI_DCL_LONG|ZEND_FFI_DCL_SIGNED|ZEND_FFI_DCL_UNSIGNED|ZEND_FFI_DCL_INT))) yy_error_sym("unexpected", sym);
- dcl->flags |= ZEND_FFI_DCL_LONG_LONG;
- } else {
- if (dcl->flags & (ZEND_FFI_DCL_TYPE_SPECIFIERS-(ZEND_FFI_DCL_LONG|ZEND_FFI_DCL_SIGNED|ZEND_FFI_DCL_UNSIGNED|ZEND_FFI_DCL_INT|ZEND_FFI_DCL_DOUBLE|ZEND_FFI_DCL_COMPLEX))) yy_error_sym("unexpected", sym);
- dcl->flags |= ZEND_FFI_DCL_LONG;
- }
- }
- "long"
- | {if (dcl->flags & (ZEND_FFI_DCL_TYPE_SPECIFIERS-(ZEND_FFI_DCL_COMPLEX))) yy_error_sym("unexpected", sym);}
- "float"
- {dcl->flags |= ZEND_FFI_DCL_FLOAT;}
- | {if (dcl->flags & (ZEND_FFI_DCL_TYPE_SPECIFIERS-(ZEND_FFI_DCL_LONG|ZEND_FFI_DCL_COMPLEX))) yy_error_sym("unexpected", sym);}
- "double"
- {dcl->flags |= ZEND_FFI_DCL_DOUBLE;}
- | {if (dcl->flags & (ZEND_FFI_DCL_TYPE_SPECIFIERS-(ZEND_FFI_DCL_CHAR|ZEND_FFI_DCL_SHORT|ZEND_FFI_DCL_LONG|ZEND_FFI_DCL_LONG_LONG|ZEND_FFI_DCL_INT))) yy_error_sym("unexpected", sym);}
- "signed"
- {dcl->flags |= ZEND_FFI_DCL_SIGNED;}
- | {if (dcl->flags & (ZEND_FFI_DCL_TYPE_SPECIFIERS-(ZEND_FFI_DCL_CHAR|ZEND_FFI_DCL_SHORT|ZEND_FFI_DCL_LONG|ZEND_FFI_DCL_LONG_LONG|ZEND_FFI_DCL_INT))) yy_error_sym("unexpected", sym);}
- "unsigned"
- {dcl->flags |= ZEND_FFI_DCL_UNSIGNED;}
- | {if (dcl->flags & ZEND_FFI_DCL_TYPE_SPECIFIERS) yy_error_sym("unexpected", sym);}
- "_Bool"
- {dcl->flags |= ZEND_FFI_DCL_BOOL;}
- | {if (dcl->flags & (ZEND_FFI_DCL_TYPE_SPECIFIERS-(ZEND_FFI_DCL_FLOAT|ZEND_FFI_DCL_DOUBLE|ZEND_FFI_DCL_LONG))) yy_error_sym("unexpected", sym);}
- ("_Complex"|"complex"|"__complex"|"__complex__")
- {dcl->flags |= ZEND_FFI_DCL_COMPLEX;}
- // | "_Atomic" "(" type_name ")" // TODO: not-implemented ???
- | {if (dcl->flags & ZEND_FFI_DCL_TYPE_SPECIFIERS) yy_error_sym("unexpected", sym);}
- struct_or_union_specifier(dcl)
- | {if (dcl->flags & ZEND_FFI_DCL_TYPE_SPECIFIERS) yy_error_sym("unexpected", sym);}
- enum_specifier(dcl)
- | {if (dcl->flags & ZEND_FFI_DCL_TYPE_SPECIFIERS) yy_error_sym("unexpected", sym);}
- {/*redeclaration of '%.*s' ??? */}
- ID(&name, &name_len)
- {dcl->flags |= ZEND_FFI_DCL_TYPEDEF_NAME;}
- {zend_ffi_resolve_typedef(name, name_len, dcl);}
- )
- ;
- struct_or_union_specifier(zend_ffi_dcl *dcl):
- ( "struct"
- {dcl->flags |= ZEND_FFI_DCL_STRUCT;}
- | "union"
- {dcl->flags |= ZEND_FFI_DCL_UNION;}
- )
- attributes(dcl)?
- ( {const char *name;}
- {size_t name_len;}
- ID(&name, &name_len)
- {zend_ffi_declare_tag(name, name_len, dcl, 1);}
- ( struct_contents(dcl)
- {zend_ffi_declare_tag(name, name_len, dcl, 0);}
- )?
- | {zend_ffi_make_struct_type(dcl);}
- struct_contents(dcl)
- )
- ;
- struct_contents(zend_ffi_dcl *dcl):
- "{"
- ( struct_declaration(dcl)
- ( ";"
- struct_declaration(dcl)
- )*
- (";")?
- )?
- "}"
- attributes(dcl)?+
- {zend_ffi_adjust_struct_size(dcl);}
- ;
- struct_declaration(zend_ffi_dcl *struct_dcl):
- {zend_ffi_dcl common_field_dcl = ZEND_FFI_ATTR_INIT;}
- specifier_qualifier_list(&common_field_dcl)
- ( /* empty */
- {zend_ffi_add_anonymous_field(struct_dcl, &common_field_dcl);}
- | struct_declarator(struct_dcl, &common_field_dcl)
- ( ","
- {zend_ffi_dcl field_dcl = common_field_dcl;}
- attributes(&field_dcl)?
- struct_declarator(struct_dcl, &field_dcl)
- )*
- )
- ;
- struct_declarator(zend_ffi_dcl *struct_dcl, zend_ffi_dcl *field_dcl):
- {const char *name = NULL;}
- {size_t name_len = 0;}
- {zend_ffi_val bits;}
- ( declarator(field_dcl, &name, &name_len)
- ( ":"
- constant_expression(&bits)
- attributes(field_dcl)?
- {zend_ffi_add_bit_field(struct_dcl, name, name_len, field_dcl, &bits);}
- | /*empty */
- attributes(field_dcl)?
- {zend_ffi_add_field(struct_dcl, name, name_len, field_dcl);}
- )
- | ":"
- constant_expression(&bits)
- {zend_ffi_add_bit_field(struct_dcl, NULL, 0, field_dcl, &bits);}
- )
- ;
- enum_specifier(zend_ffi_dcl *dcl):
- "enum"
- {dcl->flags |= ZEND_FFI_DCL_ENUM;}
- attributes(dcl)?
- ( {const char *name;}
- {size_t name_len;}
- ID(&name, &name_len)
- ( {zend_ffi_declare_tag(name, name_len, dcl, 0);}
- "{"
- enumerator_list(dcl)
- "}"
- attributes(dcl)?+
- | {zend_ffi_declare_tag(name, name_len, dcl, 1);}
- )
- | "{"
- {zend_ffi_make_enum_type(dcl);}
- enumerator_list(dcl)
- "}"
- attributes(dcl)?+
- )
- ;
- enumerator_list(zend_ffi_dcl *enum_dcl):
- {int64_t min = 0, max = 0, last = -1;}
- enumerator(enum_dcl, &min, &max, &last)
- ( ","
- enumerator(enum_dcl, &min, &max, &last)
- )*
- ","?
- ;
- enumerator(zend_ffi_dcl *enum_dcl, int64_t *min, int64_t *max, int64_t *last):
- {const char *name;}
- {size_t name_len;}
- {zend_ffi_val val = {.kind = ZEND_FFI_VAL_EMPTY};}
- ID(&name, &name_len)
- ( "="
- constant_expression(&val)
- )?
- {zend_ffi_add_enum_val(enum_dcl, name, name_len, &val, min, max, last);}
- ;
- declarator(zend_ffi_dcl *dcl, const char **name, size_t *name_len):
- {zend_ffi_dcl nested_dcl = {ZEND_FFI_DCL_CHAR, 0, 0, 0, NULL};}
- {bool nested = 0;}
- pointer(dcl)?
- ( ID(name, name_len)
- | "("
- attributes(&nested_dcl)?
- declarator(&nested_dcl, name, name_len)
- ")"
- {nested = 1;}
- )
- array_or_function_declarators(dcl, &nested_dcl)?
- {if (nested) zend_ffi_nested_declaration(dcl, &nested_dcl);}
- ;
- abstract_declarator(zend_ffi_dcl *dcl):
- {zend_ffi_dcl nested_dcl = {ZEND_FFI_DCL_CHAR, 0, 0, 0, NULL};}
- {bool nested = 0;}
- pointer(dcl)?
- ( &nested_declarator_start
- "("
- attributes(&nested_dcl)?
- abstract_declarator(&nested_dcl)
- ")"
- {nested = 1;}
- )?
- array_or_function_declarators(dcl, &nested_dcl)?
- {if (nested) zend_ffi_nested_declaration(dcl, &nested_dcl);}
- ;
- parameter_declarator(zend_ffi_dcl *dcl, const char **name, size_t *name_len):
- {zend_ffi_dcl nested_dcl = {ZEND_FFI_DCL_CHAR, 0, 0, 0, NULL};}
- {bool nested = 0;}
- pointer(dcl)?
- ( &nested_declarator_start
- "("
- attributes(&nested_dcl)?
- parameter_declarator(&nested_dcl, name, name_len)
- ")"
- {nested = 1;}
- | ID(name, name_len)
- | /* empty */
- )
- array_or_function_declarators(dcl, &nested_dcl)?
- {if (nested) zend_ffi_nested_declaration(dcl, &nested_dcl);}
- ;
- pointer(zend_ffi_dcl *dcl):
- ( "*"
- {zend_ffi_make_pointer_type(dcl);}
- type_qualifier_list(dcl)?
- )+
- ;
- array_or_function_declarators(zend_ffi_dcl *dcl, zend_ffi_dcl *nested_dcl):
- {zend_ffi_dcl dummy = ZEND_FFI_ATTR_INIT;}
- {zend_ffi_val len = {.kind = ZEND_FFI_VAL_EMPTY};}
- {HashTable *args = NULL;}
- {uint32_t attr = 0;}
- ( "["
- ( "static"
- type_qualifier_list(&dummy)?
- assignment_expression(&len)
- | type_qualifier_list(&dummy)
- ( "static" assignment_expression(&len)
- | /* empty */
- {attr |= ZEND_FFI_ATTR_INCOMPLETE_ARRAY;}
- | "*"
- {attr |= ZEND_FFI_ATTR_VLA;}
- | assignment_expression(&len)
- )
- | ( /* empty */
- {attr |= ZEND_FFI_ATTR_INCOMPLETE_ARRAY;}
- | "*"
- {attr |= ZEND_FFI_ATTR_VLA;}
- | assignment_expression(&len)
- )
- )
- "]"
- array_or_function_declarators(dcl, nested_dcl)?
- {dcl->attr |= attr;}
- {zend_ffi_make_array_type(dcl, &len);}
- | "("
- (
- parameter_declaration(&args)
- ( ","
- parameter_declaration(&args)
- )*
- (
- ","
- "..."
- {attr |= ZEND_FFI_ATTR_VARIADIC;}
- )?
- | "..."
- {attr |= ZEND_FFI_ATTR_VARIADIC;}
- )?
- ")"
- array_or_function_declarators(dcl, nested_dcl)?
- {dcl->attr |= attr;}
- {zend_ffi_make_func_type(dcl, args, nested_dcl);}
- // | "(" (ID ("," ID)*)? ")" // TODO: ANSI function not-implemented ???
- )
- ;
- parameter_declaration(HashTable **args):
- {const char *name = NULL;}
- {size_t name_len = 0;}
- {bool old_allow_vla = FFI_G(allow_vla);}
- {FFI_G(allow_vla) = 1;}
- {zend_ffi_dcl param_dcl = ZEND_FFI_ATTR_INIT;}
- specifier_qualifier_list(¶m_dcl)
- parameter_declarator(¶m_dcl, &name, &name_len)
- /*attributes(¶m_dcl)? conflict ???*/
- {zend_ffi_add_arg(args, name, name_len, ¶m_dcl);}
- {FFI_G(allow_vla) = old_allow_vla;}
- ;
- type_name(zend_ffi_dcl *dcl):
- specifier_qualifier_list(dcl)
- abstract_declarator(dcl)
- ;
- attributes(zend_ffi_dcl *dcl):
- {const char *name;}
- {size_t name_len;}
- {zend_ffi_val val;}
- (
- ("__attribute"|"__attribute__")
- "("
- "("
- attrib(dcl)
- ( ","
- attrib(dcl)
- )*
- ")"
- ")"
- | "__declspec"
- "("
- ( ID(&name, &name_len)
- (
- "("
- assignment_expression(&val)
- {zend_ffi_add_msvc_attribute_value(dcl, name, name_len, &val);}
- ")"
- )?
- )+
- ")"
- | "__cdecl"
- {zend_ffi_set_abi(dcl, ZEND_FFI_ABI_CDECL);}
- | "__stdcall"
- {zend_ffi_set_abi(dcl, ZEND_FFI_ABI_STDCALL);}
- | "__fastcall"
- {zend_ffi_set_abi(dcl, ZEND_FFI_ABI_FASTCALL);}
- | "__thiscall"
- {zend_ffi_set_abi(dcl, ZEND_FFI_ABI_THISCALL);}
- | "__vectorcall"
- {zend_ffi_set_abi(dcl, ZEND_FFI_ABI_VECTORCALL);}
- )++
- ;
- attrib(zend_ffi_dcl *dcl):
- {const char *name;}
- {size_t name_len;}
- {int n;}
- {zend_ffi_val val;}
- {bool orig_attribute_parsing;}
- ( ID(&name, &name_len)
- ( /* empty */
- {zend_ffi_add_attribute(dcl, name, name_len);}
- | "("
- {orig_attribute_parsing = FFI_G(attribute_parsing);}
- {FFI_G(attribute_parsing) = 1;}
- assignment_expression(&val)
- {zend_ffi_add_attribute_value(dcl, name, name_len, 0, &val);}
- {n = 0;}
- ( ","
- assignment_expression(&val)
- {zend_ffi_add_attribute_value(dcl, name, name_len, ++n, &val);}
- )*
- {FFI_G(attribute_parsing) = orig_attribute_parsing;}
- ")"
- )
- | "const"
- | "__const"
- | "__const__"
- )?
- ;
- initializer:
- {zend_ffi_val dummy;}
- "="
- ( assignment_expression(&dummy)
- | "{" designation? initializer ( "," designation? initializer)* ","? "}"
- )
- ;
- designation:
- {const char *name;}
- {size_t name_len;}
- {zend_ffi_val dummy;}
- ( "[" constant_expression(&dummy) "]"
- | "." ID(&name, &name_len)
- )+
- "="
- ;
- expr_list:
- {zend_ffi_val dummy;}
- assignment_expression(&dummy)
- ( ","
- assignment_expression(&dummy)
- )*
- ;
- expression(zend_ffi_val *val):
- assignment_expression(val)
- ( ","
- assignment_expression(val)
- )*
- ;
- assignment_expression(zend_ffi_val *val):
- // ( unary_expression
- // ("="|"*="|"/="|"%="|"+="|"-="|"<<="|">>="|"&="|"^="|"|=")
- // )* // TODO: not-implemented ???
- conditional_expression(val)
- ;
- constant_expression(zend_ffi_val *val):
- conditional_expression(val)
- ;
- conditional_expression(zend_ffi_val *val):
- {zend_ffi_val op2, op3;}
- logical_or_expression(val)
- ( "?"
- expression(&op2)
- ":"
- conditional_expression(&op3)
- {zend_ffi_expr_conditional(val, &op2, &op3);}
- )?
- ;
- logical_or_expression(zend_ffi_val *val):
- {zend_ffi_val op2;}
- logical_and_expression(val)
- ( "||"
- logical_and_expression(&op2)
- {zend_ffi_expr_bool_or(val, &op2);}
- )*
- ;
- logical_and_expression(zend_ffi_val *val):
- {zend_ffi_val op2;}
- inclusive_or_expression(val)
- ( "&&"
- inclusive_or_expression(&op2)
- {zend_ffi_expr_bool_and(val, &op2);}
- )*
- ;
- inclusive_or_expression(zend_ffi_val *val):
- {zend_ffi_val op2;}
- exclusive_or_expression(val)
- ( "|"
- exclusive_or_expression(&op2)
- {zend_ffi_expr_bw_or(val, &op2);}
- )*
- ;
- exclusive_or_expression(zend_ffi_val *val):
- {zend_ffi_val op2;}
- and_expression(val)
- ( "^"
- and_expression(&op2)
- {zend_ffi_expr_bw_xor(val, &op2);}
- )*
- ;
- and_expression(zend_ffi_val *val):
- {zend_ffi_val op2;}
- equality_expression(val)
- ( "&"
- equality_expression(&op2)
- {zend_ffi_expr_bw_and(val, &op2);}
- )*
- ;
- equality_expression(zend_ffi_val *val):
- {zend_ffi_val op2;}
- relational_expression(val)
- ( "=="
- relational_expression(&op2)
- {zend_ffi_expr_is_equal(val, &op2);}
- | "!="
- relational_expression(&op2)
- {zend_ffi_expr_is_not_equal(val, &op2);}
- )*
- ;
- relational_expression(zend_ffi_val *val):
- {zend_ffi_val op2;}
- shift_expression(val)
- ( "<"
- shift_expression(&op2)
- {zend_ffi_expr_is_less(val, &op2);}
- | ">"
- shift_expression(&op2)
- {zend_ffi_expr_is_greater(val, &op2);}
- | "<="
- shift_expression(&op2)
- {zend_ffi_expr_is_less_or_equal(val, &op2);}
- | ">="
- shift_expression(&op2)
- {zend_ffi_expr_is_greater_or_equal(val, &op2);}
- )*
- ;
- shift_expression(zend_ffi_val *val):
- {zend_ffi_val op2;}
- additive_expression(val)
- ( "<<"
- additive_expression(&op2)
- {zend_ffi_expr_shift_left(val, &op2);}
- | ">>"
- additive_expression(&op2)
- {zend_ffi_expr_shift_right(val, &op2);}
- )*
- ;
- additive_expression(zend_ffi_val *val):
- {zend_ffi_val op2;}
- multiplicative_expression(val)
- ( "+"
- multiplicative_expression(&op2)
- {zend_ffi_expr_add(val, &op2);}
- | "-"
- multiplicative_expression(&op2)
- {zend_ffi_expr_sub(val, &op2);}
- )*
- ;
- multiplicative_expression(zend_ffi_val *val):
- {zend_ffi_val op2;}
- cast_expression(val)
- ( "*"
- cast_expression(&op2)
- {zend_ffi_expr_mul(val, &op2);}
- | "/"
- cast_expression(&op2)
- {zend_ffi_expr_div(val, &op2);}
- | "%"
- cast_expression(&op2)
- {zend_ffi_expr_mod(val, &op2);}
- )*
- ;
- cast_expression(zend_ffi_val *val):
- {int do_cast = 0;}
- {zend_ffi_dcl dcl = ZEND_FFI_ATTR_INIT;}
- ( &( "(" type_name_start )
- "("
- type_name(&dcl)
- ")"
- {do_cast = 1;}
- )?
- unary_expression(val)
- {if (do_cast) zend_ffi_expr_cast(val, &dcl);}
- ;
- unary_expression(zend_ffi_val *val):
- {const char *name;}
- {size_t name_len;}
- {zend_ffi_dcl dcl = ZEND_FFI_ATTR_INIT;}
- ( ID(&name, &name_len)
- {zend_ffi_resolve_const(name, name_len, val);}
- (
- ( "["
- expr_list
- "]"
- | "("
- expr_list?
- ")"
- | "."
- ID(&name, &name_len)
- | "->"
- ID(&name, &name_len)
- | "++"
- | "--"
- )
- {zend_ffi_val_error(val);}
- )*
- | OCTNUMBER(val)
- | DECNUMBER(val)
- | HEXNUMBER(val)
- | FLOATNUMBER(val)
- | STRING(val)
- | CHARACTER(val)
- | "("
- expression(val)
- ")"
- | "++"
- unary_expression(val)
- {zend_ffi_val_error(val);}
- | "--"
- unary_expression(val)
- {zend_ffi_val_error(val);}
- | "&"
- cast_expression(val)
- {zend_ffi_val_error(val);}
- | "*"
- cast_expression(val)
- {zend_ffi_val_error(val);}
- | "+"
- cast_expression(val)
- {zend_ffi_expr_plus(val);}
- | "-"
- cast_expression(val)
- {zend_ffi_expr_neg(val);}
- | "~"
- cast_expression(val)
- {zend_ffi_expr_bw_not(val);}
- | "!"
- cast_expression(val)
- {zend_ffi_expr_bool_not(val);}
- | "sizeof"
- ( &( "(" type_name_start )
- "("
- type_name(&dcl)
- ")"
- {zend_ffi_expr_sizeof_type(val, &dcl);}
- | unary_expression(val)
- {zend_ffi_expr_sizeof_val(val);}
- )
- | "_Alignof"
- "("
- type_name(&dcl)
- ")"
- {zend_ffi_expr_alignof_type(val, &dcl);}
- | ("__alignof"|"__alignof__")
- ( &( "(" type_name_start )
- "("
- type_name(&dcl)
- ")"
- {zend_ffi_expr_alignof_type(val, &dcl);}
- | unary_expression(val)
- {zend_ffi_expr_alignof_val(val);}
- )
- )
- ;
- /* lookahead rules */
- nested_declarator_start:
- "("
- ( ?{!zend_ffi_is_typedef_name((const char*)yy_text, yy_pos - yy_text)}
- ID
- | "__attribute"
- | "__attribute__"
- | "__declspec"
- | "*"
- | "("
- | "["
- )
- ;
- type_name_start:
- ( ?{zend_ffi_is_typedef_name((const char*)yy_text, yy_pos - yy_text)}
- ID
- | "void"
- | "char"
- | "short"
- | "int"
- | "long"
- | "float"
- | "double"
- | "signed"
- | "unsigned"
- | "_Bool"
- | "_Complex"
- | "complex"
- | "__complex"
- | "__complex__"
- | "struct"
- | "union"
- | "enum"
- | "const"
- | "__const"
- | "__const__"
- | "restrict"
- | "__restict"
- | "__restrict__"
- | "volatile"
- | "__volatile"
- | "__volatile__"
- | "_Atomic"
- | "__attribute"
- | "__attribute__"
- | "__declspec"
- )
- ;
- /* scanner rules */
- ID(const char **name, size_t *name_len):
- /[A-Za-z_][A-Za-z_0-9]*/
- {*name = (const char*)yy_text; *name_len = yy_pos - yy_text;}
- ;
- OCTNUMBER(zend_ffi_val *val):
- /0[0-7]*([Uu](L|l|LL|l)?|[Ll][Uu]?|(LL|ll)[Uu])?/
- {zend_ffi_val_number(val, 8, (const char*)yy_text, yy_pos - yy_text);}
- ;
- DECNUMBER(zend_ffi_val *val):
- /[1-9][0-9]*([Uu](L|l|LL|l)?|[Ll][Uu]?|(LL|ll)[Uu])?/
- {zend_ffi_val_number(val, 10, (const char*)yy_text, yy_pos - yy_text);}
- ;
- HEXNUMBER(zend_ffi_val *val):
- /0[xX][0-9A-Fa-f][0-9A-Fa-f]*([Uu](L|l|LL|l)?|[Ll][Uu]?|(LL|ll)[Uu])?/
- {zend_ffi_val_number(val, 16, (const char*)yy_text + 2, yy_pos - yy_text - 2);}
- ;
- FLOATNUMBER(zend_ffi_val *val):
- /([0-9]*\.[0-9]+([Ee][\+\-]?[0-9]+)?|[0-9]+\.([Ee][\+\-]?[0-9]+)?|[0-9]+[Ee][\+\-]?[0-9]+)[flFL]?/
- {zend_ffi_val_float_number(val, (const char*)yy_text, yy_pos - yy_text);}
- ;
- STRING(zend_ffi_val *val):
- /(u8|u|U|L)?"([^"\\]|\\.)*"/
- {zend_ffi_val_string(val, (const char*)yy_text, yy_pos - yy_text);}
- ;
- CHARACTER(zend_ffi_val *val):
- /[LuU]?'([^'\\]|\\.)*'/
- {zend_ffi_val_character(val, (const char*)yy_text, yy_pos - yy_text);}
- ;
- EOL: /\r\n|\r|\n/;
- WS: /[ \t\f\v]+/;
- ONE_LINE_COMMENT: /(\/\/|#)[^\r\n]*(\r\n|\r|\n)/;
- COMMENT: /\/\*([^\*]|\*+[^\*\/])*\*+\//;
- SKIP: ( EOL | WS | ONE_LINE_COMMENT | COMMENT )*;
- %%
- int zend_ffi_parse_decl(const char *str, size_t len) {
- if (SETJMP(FFI_G(bailout))==0) {
- FFI_G(allow_vla) = 0;
- FFI_G(attribute_parsing) = 0;
- yy_buf = (unsigned char*)str;
- yy_end = yy_buf + len;
- parse();
- return SUCCESS;
- } else {
- return FAILURE;
- }
- }
- int zend_ffi_parse_type(const char *str, size_t len, zend_ffi_dcl *dcl) {
- int sym;
- if (SETJMP(FFI_G(bailout))==0) {
- FFI_G(allow_vla) = 0;
- FFI_G(attribute_parsing) = 0;
- yy_pos = yy_text = yy_buf = (unsigned char*)str;
- yy_end = yy_buf + len;
- yy_line = 1;
- sym = parse_type_name(get_sym(), dcl);
- if (sym != YY_EOF) {
- yy_error_sym("<EOF> expected, got", sym);
- }
- zend_ffi_validate_type_name(dcl);
- return SUCCESS;
- } else {
- return FAILURE;
- };
- }
- static void yy_error(const char *msg) {
- zend_ffi_parser_error("%s at line %d", msg, yy_line);
- }
- static void yy_error_sym(const char *msg, int sym) {
- zend_ffi_parser_error("%s '%s' at line %d", msg, sym_name[sym], yy_line);
- }
|