Skip to content

Commit b13aa2b

Browse files
committed
Add readme
1 parent e3e446e commit b13aa2b

File tree

1 file changed

+238
-0
lines changed

1 file changed

+238
-0
lines changed

README.md

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
# Simple C-lang Preprocessor
2+
3+
This implementation of a preprocessor based in part on
4+
[ISO/IEC 9899:TC2](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf).
5+
6+
## Requirements
7+
8+
- PHP >= 8.0
9+
10+
## Installation
11+
12+
Library is available as composer repository and can be installed using the
13+
following command in a root of your project.
14+
15+
```sh
16+
$ composer require ffi/preprocessor
17+
```
18+
19+
## Usage
20+
21+
```php
22+
use FFI\Preprocessor\Preprocessor;
23+
24+
$pre = new Preprocessor();
25+
26+
echo $pre->process('
27+
#define VK_DEFINE_HANDLE(object) typedef struct object##_T* object;
28+
29+
#if !defined(VK_DEFINE_NON_DISPATCHABLE_HANDLE)
30+
#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
31+
#define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef struct object##_T *object;
32+
#else
33+
#define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object;
34+
#endif
35+
#endif
36+
37+
VK_DEFINE_HANDLE(VkInstance)
38+
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSemaphore)
39+
');
40+
41+
//
42+
// Expected Output:
43+
//
44+
// typedef struct VkInstance_T* VkInstance;
45+
// typedef uint64_t VkSemaphore;
46+
//
47+
```
48+
49+
## Directives
50+
51+
### Supported Directives
52+
53+
- [x] `#include "file.h"` local-first include
54+
- [x] `#include <file.h>` global-first include
55+
- [x] `#define name` defining directives
56+
- [x] `#define name value` object-like macro
57+
- [x] `#define name(arg) value` function-like macro
58+
- [x] `#define name(arg) xxx##arg` concatenation
59+
- [x] `#define name(arg) #arg` stringizing
60+
- [x] `#undef name` removing directives
61+
- [x] `#ifdef name` "if directive defined" condition
62+
- [x] `#ifndef name` "if directive not defined" condition
63+
- [x] `#if EXPRESSION` if condition
64+
- [x] `#elif EXPRESSION` else if condition
65+
- [x] `#else` else condition
66+
- [x] `#endif` completion of a condition
67+
- [x] `#error message` error message directive
68+
- [x] `#warning message` warning message directive
69+
- [ ] `#line 66 "filename"` line and file override
70+
- [ ] `#pragma XXX` compiler control
71+
- [ ] `#pragma once`
72+
- [ ] `#assert XXX` compiler assertion
73+
- [ ] `#unassert XXX` compiler assertion
74+
- [ ] `#ident XXX`
75+
- [ ] `#sccs XXX`
76+
77+
### Expression Grammar
78+
79+
#### Comparison Operators
80+
81+
- [x] `A > B` greater than
82+
- [x] `A < B` less than
83+
- [x] `A == B` equal
84+
- [x] `A != B` not equal
85+
- [x] `A >= B` greater than or equal
86+
- [x] `A <= B` less than or equal
87+
88+
#### Logical Operators
89+
90+
- [x] `! A` logical NOT
91+
- [x] `A && B` conjunction
92+
- [x] `A || B` disjunction
93+
- [x] `(...)` grouping
94+
95+
#### Arithmetic Operators
96+
97+
- [x] `A + B` math addition
98+
- [x] `A - B` math subtraction
99+
- [x] `A * B` math multiplication
100+
- [x] `A / B` math division
101+
- [x] `A % B` modulo
102+
- [ ] `A++` increment
103+
- [x] `++A` prefix form
104+
- [ ] `A--` decrement
105+
- [x] `--A` prefix form
106+
- [x] `+A` unary plus
107+
- [x] `-A` unary minus
108+
- [ ] `&A` unary addr
109+
- [ ] `*A` unary pointer
110+
111+
#### Bitwise Operators
112+
113+
- [x] `~A` bitwise NOT
114+
- [x] `A & B` bitwise AND
115+
- [x] `A | B` bitwise OR
116+
- [x] `A ^ B` bitwise XOR
117+
- [x] `A << B` bitwise left shift
118+
- [x] `A >> B` bitwise right shift
119+
120+
#### Other Operators
121+
122+
- [x] `defined(X)` defined macro
123+
- [ ] `A ? B : C` ternary
124+
- [ ] `sizeof VALUE` sizeof
125+
- [ ] `sizeof(TYPE)` sizeof type
126+
127+
### Literals
128+
129+
- [x] `true`, `false` boolean
130+
- [x] `42` decimal integer literal
131+
- [x] `42u`, `42U` unsigned int
132+
- [x] `42l`, `42L` long int
133+
- [x] `42ul`, `42UL` unsigned long int
134+
- [x] `42ll`, `42LL` long long int
135+
- [x] `42ull`, `42ULL` unsigned long long int
136+
- [x] `042` octal integer literal
137+
- [x] `0x42` hexadecimal integer literal
138+
- [x] `0b42` binary integer literal
139+
- [x] `"string"` string (char array)
140+
- [x] `L"string"` string (wide char array)
141+
- [x] `"\•"` escape sequences in strings
142+
- [ ] `"\•••"` arbitrary octal value in strings
143+
- [ ] `"\X••"` arbitrary hexadecimal value in strings
144+
- [ ] `'x'` char literal
145+
- [ ] `'\•'` escape sequences
146+
- [ ] `'\•••'` arbitrary octal value
147+
- [ ] `'\X••'` arbitrary hexadecimal value
148+
- [ ] `L'x'` wide character literal
149+
- [ ] `42.0` double
150+
- [ ] `42f`, `42F` float
151+
- [ ] `42l`, `42L` long double
152+
- [ ] `42E` exponential form
153+
- [ ] `0.42e23` exponential form
154+
- [ ] `NULL` null macro
155+
156+
### Type Casting
157+
158+
- [x] `(char)42`
159+
- [x] `(short)42`
160+
- [x] `(int)42`
161+
- [x] `(long)42`
162+
- [x] `(float)42`
163+
- [x] `(double)42`
164+
- [x] `(bool)42` (Out of ISO/IEC 9899:TC2 specification)
165+
- [x] `(string)42` (Out of ISO/IEC 9899:TC2 specification)
166+
- [ ] `(void)42`
167+
- [ ] `(long type)42` Casting to a long type (`long int`, `long double`, etc)
168+
- [ ] `(const type)42` Casting to a constant type (`const char`, etc)
169+
- [ ] `(unsigned type)42` Casting to unsigned type (`unsigned int`, `unsigned long`, etc)
170+
- [ ] `(signed type)42` Casting to signed type (`signed int`, `signed long`, etc)
171+
- [ ] Pointers (`void *`, etc)
172+
- [ ] References (`unsigned int`, `unsigned long`, etc)
173+
174+
### Object Like Directive
175+
176+
```php
177+
use FFI\Preprocessor\Preprocessor;
178+
use FFI\Preprocessor\Directive\ObjectLikeDirective;
179+
180+
$pre = new Preprocessor();
181+
182+
// #define A
183+
$pre->define('A');
184+
185+
// #define B 42
186+
$pre->define('B', '42');
187+
188+
// #define С 42
189+
$pre->define('С', new ObjectLikeDirective('42'));
190+
```
191+
192+
## Function Like Directive
193+
194+
```php
195+
use FFI\Preprocessor\Preprocessor;
196+
use FFI\Preprocessor\Directive\FunctionLikeDirective;
197+
198+
$pre = new Preprocessor();
199+
200+
// #define C(object) object##_T* object;
201+
$pre->define('C', function (string $arg) {
202+
return "${arg}_T* ${arg};";
203+
});
204+
205+
// #define D(object) object##_T* object;
206+
$pre->define('D', new FunctionLikeDirective(['object'], 'object##_T* object'));
207+
```
208+
209+
## Include Directories
210+
211+
```php
212+
use FFI\Preprocessor\Preprocessor;
213+
214+
$pre = new Preprocessor();
215+
216+
$pre->include('/path/to/directory');
217+
$pre->exclude('some');
218+
```
219+
220+
## Message Handling
221+
222+
```php
223+
use FFI\Preprocessor\Preprocessor;
224+
225+
$logger = new Psr3LoggerImplementation();
226+
227+
$pre = new Preprocessor($logger);
228+
229+
$pre->process('
230+
#error Error message
231+
// Will be sent to the logger:
232+
// - LoggerInterface::error("Error message")
233+
234+
#warning Warning message
235+
// Will be sent to the logger:
236+
// - LoggerInterface::warning("Warning message")
237+
');
238+
```

0 commit comments

Comments
 (0)