* grammar and libs

* gitignore

* parsing

* allow empty line as root statement

* tolerate #if

* config def changes

* s

* ant build

* workaround

* compiled tool

* grammar for unions

* parse unions

* layout logic

* fix union alignment

* union in config

* jar

* comment

* jar

* jar

* no prefix on root struct

* stray space

* normalize some enums
This commit is contained in:
Matthew Kennedy 2021-06-18 09:31:23 -07:00 committed by GitHub
parent 56fd45a81e
commit e7e9ab0d5c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 882 additions and 10 deletions

View File

@ -66,7 +66,7 @@
! all the sub-structures are going to be nested within the primary structure, that's
! needed to get a proper TunerStudio file
struct persistent_config_s
struct_no_prefix persistent_config_s
struct_no_prefix engine_configuration_s
@ -302,8 +302,8 @@ custom vvt_mode_e 1 bits, U08, @OFFSET@, [0:3], @@vvt_mode_e_enum@@
! todo: convert slow ADC to software scheduler and make TIM8 available
! todo: maybe convert fast ADC to software scheduler as well? less sure about that
#define brain_input_pin_e_enum "NONE", "INVALID", "INVALID", "PA1", "PA2", "PA3", "INVALID", "PA5", "PA6", "PA7", "PA8", "PA9", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "PA15", "INVALID", "INVALID", "INVALID", "PB3", "PB4", "PB5", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "PC6", "PC7", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "PE5", "PE6", "INVALID", "INVALID", "PE9", "INVALID", "PE11", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
custom brain_input_pin_e 1 bits, U08, @OFFSET@, [0:7], @@brain_input_pin_e_enum@@
#define brain_input_pin_e_enum "NONE", "INVALID", "INVALID", "PA1", "PA2", "PA3", "INVALID", "PA5", "PA6", "PA7", "PA8", "PA9", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "PA15", "INVALID", "INVALID", "INVALID", "PB3", "PB4", "PB5", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "PC6", "PC7", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "PE5", "PE6", "INVALID", "INVALID", "PE9", "INVALID", "PE11", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
custom brain_input_pin_e 1 bits, U08, @OFFSET@, [0:7], @@brain_input_pin_e_enum@@
!
! 'brain_pin_e' is the most flexible kind of pin
@ -312,14 +312,14 @@ custom brain_input_pin_e 1 bits, U08, @OFFSET@, [0:7], @@brain_input_pin_e_
! 'switch_input_pin_e' is a slow digital input suitable for clutch or brake pedal switch but not suitable for VSS or Flex sensor input
!
#define brain_pin_e_enum "NONE", "INVALID", "PA0", "PA1", "PA2", "PA3", "PA4", "PA5", "PA6", "PA7", "PA8", "PA9", "PA10", "PA11", "PA12", "PA13", "PA14", "PA15", "PB0", "PB1", "PB2", "PB3", "PB4", "PB5", "PB6", "PB7", "PB8", "PB9", "PB10", "PB11", "PB12", "PB13", "PB14", "PB15", "PC0", "PC1", "PC2", "PC3", "PC4", "PC5", "PC6", "PC7", "PC8", "PC9", "PC10", "PC11", "PC12", "PC13", "PC14", "PC15", "PD0", "PD1", "PD2", "PD3", "PD4", "PD5", "PD6", "PD7", "PD8", "PD9", "PD10", "PD11", "PD12", "PD13", "PD14", "PD15", "PE0", "PE1", "PE2", "PE3", "PE4", "PE5", "PE6","PE7","PE8","PE9","PE10","PE11","PE12","PE13","PE14","PE15", "PF0","PF1","PF2","PF3","PF4","PF5","PF6","PF7","PF8","PF9","PF10","PF11","PF12","PF13","PF14","PF15", "PG0","PG1","PG2","PG3","PG4","PG5","PG6","PG7","PG8","PG9","PG10","PG11","PG12","PG13","PG14","PG15", "PH0","PH1","PH2","PH3","PH4","PH5","PH6","PH7","PH8","PH9","PH10","PH11","PH12","PH13","PH14","PH15", "PI0","PI1","PI2","PI3","PI4","PI5","PI6","PI7","PI8","PI9","PI10","PI11","PI12","PI13","PI14","PI15", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
#define switch_input_pin_e_enum "NONE", "INVALID", "PA0", "PA1", "PA2", "PA3", "PA4", "PA5", "PA6", "PA7", "PA8", "PA9", "PA10", "PA11", "PA12", "PA13", "PA14", "PA15", "PB0", "PB1", "PB2", "PB3", "PB4", "PB5", "PB6", "PB7", "PB8", "PB9", "PB10", "PB11", "PB12", "PB13", "PB14", "PB15", "PC0", "PC1", "PC2", "PC3", "PC4", "PC5", "PC6", "PC7", "PC8", "PC9", "PC10", "PC11", "PC12", "PC13", "PC14", "PC15", "PD0", "PD1", "PD2", "PD3", "PD4", "PD5", "PD6", "PD7", "PD8", "PD9", "PD10", "PD11", "PD12", "PD13", "PD14", "PD15", "PE0", "PE1", "PE2", "PE3", "PE4", "PE5", "PE6","PE7","PE8","PE9","PE10","PE11","PE12","PE13","PE14","PE15", "PF0","PF1","PF2","PF3","PF4","PF5","PF6","PF7","PF8","PF9","PF10","PF11","PF12","PF13","PF14","PF15", "PG0","PG1","PG2","PG3","PG4","PG5","PG6","PG7","PG8","PG9","PG10","PG11","PG12","PG13","PG14","PG15", "PH0","PH1","PH2","PH3","PH4","PH5","PH6","PH7","PH8","PH9","PH10","PH11","PH12","PH13","PH14","PH15", "PI0","PI1","PI2","PI3","PI4","PI5","PI6","PI7","PI8","PI9","PI10","PI11","PI12","PI13","PI14","PI15", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
#define brain_pin_e_enum "NONE", "INVALID", "PA0", "PA1", "PA2", "PA3", "PA4", "PA5", "PA6", "PA7", "PA8", "PA9", "PA10", "PA11", "PA12", "PA13", "PA14", "PA15", "PB0", "PB1", "PB2", "PB3", "PB4", "PB5", "PB6", "PB7", "PB8", "PB9", "PB10", "PB11", "PB12", "PB13", "PB14", "PB15", "PC0", "PC1", "PC2", "PC3", "PC4", "PC5", "PC6", "PC7", "PC8", "PC9", "PC10", "PC11", "PC12", "PC13", "PC14", "PC15", "PD0", "PD1", "PD2", "PD3", "PD4", "PD5", "PD6", "PD7", "PD8", "PD9", "PD10", "PD11", "PD12", "PD13", "PD14", "PD15", "PE0", "PE1", "PE2", "PE3", "PE4", "PE5", "PE6", "PE7", "PE8", "PE9", "PE10", "PE11", "PE12", "PE13", "PE14", "PE15", "PF0", "PF1", "PF2", "PF3", "PF4", "PF5", "PF6", "PF7", "PF8", "PF9", "PF10", "PF11", "PF12", "PF13", "PF14", "PF15", "PG0", "PG1", "PG2", "PG3", "PG4", "PG5", "PG6", "PG7", "PG8", "PG9", "PG10", "PG11", "PG12", "PG13", "PG14", "PG15", "PH0", "PH1", "PH2", "PH3", "PH4", "PH5", "PH6", "PH7", "PH8", "PH9", "PH10", "PH11", "PH12", "PH13", "PH14", "PH15", "PI0", "PI1", "PI2", "PI3", "PI4", "PI5", "PI6", "PI7", "PI8", "PI9", "PI10", "PI11", "PI12", "PI13", "PI14", "PI15", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
#define switch_input_pin_e_enum "NONE", "INVALID", "PA0", "PA1", "PA2", "PA3", "PA4", "PA5", "PA6", "PA7", "PA8", "PA9", "PA10", "PA11", "PA12", "PA13", "PA14", "PA15", "PB0", "PB1", "PB2", "PB3", "PB4", "PB5", "PB6", "PB7", "PB8", "PB9", "PB10", "PB11", "PB12", "PB13", "PB14", "PB15", "PC0", "PC1", "PC2", "PC3", "PC4", "PC5", "PC6", "PC7", "PC8", "PC9", "PC10", "PC11", "PC12", "PC13", "PC14", "PC15", "PD0", "PD1", "PD2", "PD3", "PD4", "PD5", "PD6", "PD7", "PD8", "PD9", "PD10", "PD11", "PD12", "PD13", "PD14", "PD15", "PE0", "PE1", "PE2", "PE3", "PE4", "PE5", "PE6", "PE7", "PE8", "PE9", "PE10", "PE11", "PE12", "PE13", "PE14", "PE15", "PF0", "PF1", "PF2", "PF3", "PF4", "PF5", "PF6", "PF7", "PF8", "PF9", "PF10", "PF11", "PF12", "PF13", "PF14", "PF15", "PG0", "PG1", "PG2", "PG3", "PG4", "PG5", "PG6", "PG7", "PG8", "PG9", "PG10", "PG11", "PG12", "PG13", "PG14", "PG15", "PH0", "PH1", "PH2", "PH3", "PH4", "PH5", "PH6", "PH7", "PH8", "PH9", "PH10", "PH11", "PH12", "PH13", "PH14", "PH15", "PI0", "PI1", "PI2", "PI3", "PI4", "PI5", "PI6", "PI7", "PI8", "PI9", "PI10", "PI11", "PI12", "PI13", "PI14", "PI15", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
custom brain_pin_e 1 bits, U08, @OFFSET@, [0:7], @@brain_pin_e_enum@@
custom switch_input_pin_e 1 bits, U08, @OFFSET@, [0:7], @@switch_input_pin_e_enum@@
custom brain_pin_e 1 bits, U08, @OFFSET@, [0:7], @@brain_pin_e_enum@@
custom switch_input_pin_e 1 bits, U08, @OFFSET@, [0:7], @@switch_input_pin_e_enum@@
#define output_pin_e_enum "NONE", "INVALID", "PA0", "PA1", "PA2", "PA3", "PA4", "PA5", "PA6", "PA7", "PA8", "PA9", "PA10", "PA11", "PA12", "PA13", "PA14", "PA15", "PB0", "PB1", "PB2", "PB3", "PB4", "PB5", "PB6", "PB7", "PB8", "PB9", "PB10", "PB11", "PB12", "PB13", "PB14", "PB15", "PC0", "PC1", "PC2", "PC3", "PC4", "PC5", "PC6", "PC7", "PC8", "PC9", "PC10", "PC11", "PC12", "PC13", "PC14", "PC15", "PD0", "PD1", "PD2", "PD3", "PD4", "PD5", "PD6", "PD7", "PD8", "PD9", "PD10", "PD11", "PD12", "PD13", "PD14", "PD15", "PE0", "PE1", "PE2", "PE3", "PE4", "PE5", "PE6","PE7","PE8","PE9","PE10","PE11","PE12","PE13","PE14","PE15", "PF0","PF1","PF2","PF3","PF4","PF5","PF6","PF7","PF8","PF9","PF10","PF11","PF12","PF13","PF14","PF15", "PG0","PG1","PG2","PG3","PG4","PG5","PG6","PG7","PG8","PG9","PG10","PG11","PG12","PG13","PG14","PG15", "PH0","PH1","PH2","PH3","PH4","PH5","PH6","PH7","PH8","PH9","PH10","PH11","PH12","PH13","PH14","PH15", "PI0","PI1","PI2","PI3","PI4","PI5","PI6","PI7","PI8","PI9","PI10","PI11","PI12","PI13","PI14","PI15", "MC33972_1", "MC33972_2", "MC33972_3", "MC33972_4", "MC33972_5", "MC33972_6", "MC33972_7", "MC33972_8", "MC33972_9", "MC33972_10", "MC33972_11", "MC33972_12", "MC33972_13", "MC33972_14", "MC33972_15", "MC33972_16", "MC33972_17", "MC33972_18", "MC33972_19", "MC33972_20", "MC33972_21", "MC33972_22", "TLE8888_1", "TLE8888_2", "TLE8888_3", "TLE8888_4", "TLE8888_5", "TLE8888_6", "TLE8888_7", "TLE8888_8", "TLE8888_9", "TLE8888_10", "TLE8888_11", "TLE8888_12", "TLE8888_13", "TLE8888_14", "TLE8888_15", "TLE8888_16", "TLE8888_17", "TLE8888_18", "TLE8888_19", "TLE8888_20", "TLE8888_21", "TLE8888_22", "TLE8888_23", "TLE8888_24", "TLE8888_25", "TLE8888_26", "TLE8888_27", "TLE8888_28", "INVALID", "INVALID", "INVALID", "TLE6240_1", "TLE6240_2", "TLE6240_3", "TLE6240_4", "TLE6240_5", "TLE6240_6", "TLE6240_7", "TLE6240_8", "TLE6240_9", "TLE6240_10", "TLE6240_11", "TLE6240_12", "TLE6240_13", "TLE6240_14", "TLE6240_15", "TLE6240_16", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
custom output_pin_e 1 bits, U08, @OFFSET@, [0:7], @@output_pin_e_enum@@
#define output_pin_e_enum "NONE", "INVALID", "PA0", "PA1", "PA2", "PA3", "PA4", "PA5", "PA6", "PA7", "PA8", "PA9", "PA10", "PA11", "PA12", "PA13", "PA14", "PA15", "PB0", "PB1", "PB2", "PB3", "PB4", "PB5", "PB6", "PB7", "PB8", "PB9", "PB10", "PB11", "PB12", "PB13", "PB14", "PB15", "PC0", "PC1", "PC2", "PC3", "PC4", "PC5", "PC6", "PC7", "PC8", "PC9", "PC10", "PC11", "PC12", "PC13", "PC14", "PC15", "PD0", "PD1", "PD2", "PD3", "PD4", "PD5", "PD6", "PD7", "PD8", "PD9", "PD10", "PD11", "PD12", "PD13", "PD14", "PD15", "PE0", "PE1", "PE2", "PE3", "PE4", "PE5", "PE6", "PE7", "PE8", "PE9", "PE10", "PE11", "PE12", "PE13", "PE14", "PE15", "PF0", "PF1", "PF2", "PF3", "PF4", "PF5", "PF6", "PF7", "PF8", "PF9", "PF10", "PF11", "PF12", "PF13", "PF14", "PF15", "PG0", "PG1", "PG2", "PG3", "PG4", "PG5", "PG6", "PG7", "PG8", "PG9", "PG10", "PG11", "PG12", "PG13", "PG14", "PG15", "PH0", "PH1", "PH2", "PH3", "PH4", "PH5", "PH6", "PH7", "PH8", "PH9", "PH10", "PH11", "PH12", "PH13", "PH14", "PH15", "PI0", "PI1", "PI2", "PI3", "PI4", "PI5", "PI6", "PI7", "PI8", "PI9", "PI10", "PI11", "PI12", "PI13", "PI14", "PI15", "MC33972_1", "MC33972_2", "MC33972_3", "MC33972_4", "MC33972_5", "MC33972_6", "MC33972_7", "MC33972_8", "MC33972_9", "MC33972_10", "MC33972_11", "MC33972_12", "MC33972_13", "MC33972_14", "MC33972_15", "MC33972_16", "MC33972_17", "MC33972_18", "MC33972_19", "MC33972_20", "MC33972_21", "MC33972_22", "TLE8888_1", "TLE8888_2", "TLE8888_3", "TLE8888_4", "TLE8888_5", "TLE8888_6", "TLE8888_7", "TLE8888_8", "TLE8888_9", "TLE8888_10", "TLE8888_11", "TLE8888_12", "TLE8888_13", "TLE8888_14", "TLE8888_15", "TLE8888_16", "TLE8888_17", "TLE8888_18", "TLE8888_19", "TLE8888_20", "TLE8888_21", "TLE8888_22", "TLE8888_23", "TLE8888_24", "TLE8888_25", "TLE8888_26", "TLE8888_27", "TLE8888_28", "INVALID", "INVALID", "INVALID", "TLE6240_1", "TLE6240_2", "TLE6240_3", "TLE6240_4", "TLE6240_5", "TLE6240_6", "TLE6240_7", "TLE6240_8", "TLE6240_9", "TLE6240_10", "TLE6240_11", "TLE6240_12", "TLE6240_13", "TLE6240_14", "TLE6240_15", "TLE6240_16", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
custom output_pin_e 1 bits, U08, @OFFSET@, [0:7], @@output_pin_e_enum@@
#define pin_output_mode_e_enum "default", "default inverted", "open collector", "open collector inverted"
custom pin_output_mode_e 1 bits, U08, @OFFSET@, [0:1], @@pin_output_mode_e_enum@@
@ -675,7 +675,7 @@ adc_channel_e fuelLevelSensor;+This is the processor pin that your fuel level se
struct trigger_config_s @brief Trigger wheel(s) configuration
#define trigger_type_e_enum "custom toothed wheel", "Ford Aspire", "Dodge Neon 1995", "Miata NA", "Miata NB", "GM_7X", "Cooper R50", "Mazda SOHC 4", "60/2", "36/1", "Honda 4+24+1", "Mitsubishi", "Honda 4+24", "Honda 1+4+24", "Dodge Neon 2003", "Mazda DOHC 1+4", "1+1", "INVALID", "Single Tooth", "Dodge Ram 1+16", "60/2 VW", "Honda 1+24", "Dodge Stratus", "36_2_2_2", "Nissan Primera", "dev 2JZ 3/34 simulator", "Rover K", "GM LS 24", "Honda CBR 600", "2JZ_1_12", "Honda CBR 600 custom", "3/1 skipped" , "Dodge Neon 2003 crank", "Miata VVT", "trg34", "trg35", "Subaru 7+6", "Jeep 18-2-2-2", "WIP", "Dodge Neon 1995 crank only", "Jeep XJ 4 cyl", "FiatIAQ_P8", "Mazda Z5", "trg43", "Renix 44-2-2", "Renix 66-2-2-2", "Honda K 12+1", "trg47", "36/2", "Subaru SVX", "1+16", "Subaru 7 without 6", "trg52", "TriTach", "GM 60/2/2/2", "Skoda Favorit", "Barra 3+1 Cam", "Kawa KX450F", "trg58", "trg59", "trg60", "INVALID"
#define trigger_type_e_enum "custom toothed wheel", "Ford Aspire", "Dodge Neon 1995", "Miata NA", "Miata NB", "GM_7X", "Cooper R50", "Mazda SOHC 4", "60/2", "36/1", "Honda 4+24+1", "Mitsubishi", "Honda 4+24", "Honda 1+4+24", "Dodge Neon 2003", "Mazda DOHC 1+4", "1+1", "INVALID", "Single Tooth", "Dodge Ram 1+16", "60/2 VW", "Honda 1+24", "Dodge Stratus", "36_2_2_2", "Nissan Primera", "dev 2JZ 3/34 simulator", "Rover K", "GM LS 24", "Honda CBR 600", "2JZ_1_12", "Honda CBR 600 custom", "3/1 skipped", "Dodge Neon 2003 crank", "Miata VVT", "trg34", "trg35", "Subaru 7+6", "Jeep 18-2-2-2", "WIP", "Dodge Neon 1995 crank only", "Jeep XJ 4 cyl", "FiatIAQ_P8", "Mazda Z5", "trg43", "Renix 44-2-2", "Renix 66-2-2-2", "Honda K 12+1", "trg47", "36/2", "Subaru SVX", "1+16", "Subaru 7 without 6", "trg52", "TriTach", "GM 60/2/2/2", "Skoda Favorit", "Barra 3+1 Cam", "Kawa KX450F", "trg58", "trg59", "trg60", "INVALID"
custom trigger_type_e 4 bits, U32, @OFFSET@, [0:5], @@trigger_type_e_enum@@
trigger_type_e type;+https://github.com/rusefi/rusefi/wiki/All-Supported-Triggers\nset trigger_type X
@ -1620,6 +1620,11 @@ lambda_table_t lambdaTable;
afr_table_t lambdaTable;
#endif
! union
! lambda_table_t lambdaTable
! afr_table_t afrTable
! end_union
float[FUEL_LOAD_COUNT] lambdaLoadBins;;"", 1, 0.0, 0, 500.0, 2
float[FUEL_RPM_COUNT] lambdaRpmBins;;"RPM", 1, 0.0, 0, 18000.0, 2

Binary file not shown.

View File

@ -95,10 +95,17 @@ scalarField: identifier FsioVisible? identifier (fieldOptionsList)?;
arrayField: identifier '[' arrayLengthSpec Iterate? ']' identifier SemicolonedString? (fieldOptionsList)?;
bitField: Bit identifier (',' QuotedString ',' QuotedString)? ('(' 'comment' ':' QuotedString ')')? SemicolonedSuffix?;
unionField: 'union' ENDL+ fields 'end_union';
field
: scalarField
| arrayField
| bitField
| unionField
;
fields
: (field ENDL+)+
;
// Indicates X bytes of free space

View File

@ -151,6 +151,13 @@ public class ParseState extends RusefiConfigGrammarBaseListener {
scope = new Scope();
}
@Override
public void enterUnionField(RusefiConfigGrammarParser.UnionFieldContext ctx) {
// Unions behave like a struct as far as scope is concerned (but is processed differently later
// to overlap all members, instead of placing them in sequence as in a struct)
enterStruct(null);
}
void handleFieldOptionsList(FieldOptions options, RusefiConfigGrammarParser.FieldOptionsListContext ctx) {
// Null means no options were configured, use defaults
if (ctx == null) {
@ -412,6 +419,23 @@ public class ParseState extends RusefiConfigGrammarBaseListener {
}
}
@Override
public void exitUnionField(RusefiConfigGrammarParser.UnionFieldContext ctx) {
assert(scope != null);
assert(scope.structFields != null);
// unions must have at least 1 member
assert(!scope.structFields.isEmpty());
Union u = new Union(scope.structFields);
// Restore the containing scope
scope = scopes.pop();
// Lastly, add the union to the scope
scope.structFields.add(u);
}
private Stack<Float> evalStack = new Stack<>();

View File

@ -0,0 +1,32 @@
package com.rusefi.newparse.layout;
import com.rusefi.newparse.parsing.*;
import java.io.PrintStream;
public class ArrayIterateScalarLayout extends ArrayLayout {
public ArrayIterateScalarLayout(PrototypeField prototype, int length) {
super(prototype, length);
}
private void emitOne(PrintStream ps, StructNamePrefixer prefixer, int offset, int idx) {
// Set element's position within the array
this.prototypeLayout.setOffset(offset + this.prototypeLayout.getSize() * idx);
// Put a 1-based index on the end of the name to distinguish in TS
prefixer.setSuffix(Integer.toString(idx + 1));
this.prototypeLayout.writeTunerstudioLayout(ps, prefixer);
prefixer.resetSuffix();
}
@Override
public void writeTunerstudioLayout(PrintStream ps, StructNamePrefixer prefixer) {
// Time to iterate: emit one scalar per array element, with the name modified accordingly
for (int i = 0; i < length; i++) {
emitOne(ps, prefixer, this.offset, i);
}
}
// C layout is the same if iterated or not, use default implementation
}

View File

@ -0,0 +1,32 @@
package com.rusefi.newparse.layout;
import com.rusefi.newparse.parsing.*;
import java.io.PrintStream;
public class ArrayIterateStructLayout extends ArrayLayout {
public ArrayIterateStructLayout(StructField prototype, int length) {
super(prototype, length);
}
private void emitOne(PrintStream ps, StructNamePrefixer prefixer, int offset, int idx) {
// Set element's position within the array
this.prototypeLayout.setOffset(offset + this.prototypeLayout.getSize() * idx);
// Put a 1-based index on the end of the name to distinguish in TS
prefixer.setSuffix(Integer.toString(idx + 1));
this.prototypeLayout.writeTunerstudioLayout(ps, prefixer);
prefixer.resetSuffix();
}
@Override
public void writeTunerstudioLayout(PrintStream ps, StructNamePrefixer prefixer) {
// Time to iterate: emit one scalar per array element, with the name modified accordingly
for (int i = 0; i < this.length; i++) {
emitOne(ps, prefixer, this.offset, i);
}
}
// C layout is the same if iterated or not, use default implementation
}

View File

@ -0,0 +1,69 @@
package com.rusefi.newparse.layout;
import com.rusefi.newparse.parsing.*;
import java.io.PrintStream;
public class ArrayLayout extends Layout {
protected final int length;
protected final Layout prototypeLayout;
public ArrayLayout(PrototypeField prototype, int length) {
this.length = length;
if (prototype instanceof ScalarField) {
prototypeLayout = new ScalarLayout((ScalarField)prototype);
} else if (prototype instanceof EnumField) {
prototypeLayout = new EnumLayout((EnumField) prototype);
} else if (prototype instanceof StringField) {
prototypeLayout = new StringLayout((StringField) prototype);
} else if (prototype instanceof StructField) {
StructField structPrototype = (StructField)prototype;
prototypeLayout = new StructLayout(0, prototype.name, structPrototype.struct);
} else {
throw new RuntimeException("unexpected field type during array layout");
}
}
@Override
public int getSize() {
return this.prototypeLayout.getSize() * this.length;
}
@Override
public int getAlignment() {
// Arrays only need to be aligned on the alignment of the element, not the whole array
return this.prototypeLayout.getAlignment();
}
@Override
public void setOffset(int offset) {
super.setOffset(offset);
this.prototypeLayout.setOffset(offset);
}
@Override
public void setOffsetWithinStruct(int offset) {
super.setOffsetWithinStruct(offset);
this.prototypeLayout.setOffsetWithinStruct(offset);
}
@Override
public String toString() {
return "Array of " + this.prototypeLayout.toString() + " length " + this.length + " " + super.toString();
}
@Override
public void writeTunerstudioLayout(PrintStream ps, StructNamePrefixer prefixer) {
this.prototypeLayout.writeTunerstudioLayout(ps, prefixer, this.length);
}
@Override
public void writeCLayout(PrintStream ps) {
// Skip zero length arrays, they may be used for padding
if (this.length > 0) {
this.prototypeLayout.writeCLayout(ps, this.length);
}
}
}

View File

@ -0,0 +1,84 @@
package com.rusefi.newparse.layout;
import com.rusefi.newparse.parsing.BitGroup;
import com.rusefi.newparse.parsing.EnumField;
import com.rusefi.newparse.parsing.Type;
import com.rusefi.newparse.parsing.UnusedField;
import java.io.PrintStream;
import java.util.List;
import java.util.stream.Collectors;
public class BitGroupLayout extends Layout {
private class BitLayout {
public final String name;
public final String comment;
public BitLayout(String name, String comment) {
this.name = name;
this.comment = comment;
}
}
private final List<BitLayout> bits;
public BitGroupLayout(BitGroup bitGroup) {
int size = bitGroup.bitFields.size();
if (size > 32) {
throw new RuntimeException("tried to create bit group starting with " + bitGroup.bitFields.get(0).name + " but it contained " + size + " which is more than the maximum of 32.");
}
this.bits = bitGroup.bitFields.stream().map(bf -> new BitLayout(bf.name, bf.comment)).collect(Collectors.toList());
}
@Override
public int getSize() {
return 4;
}
@Override
public String toString() {
return "Bit group " + super.toString();
}
@Override
public void writeTunerstudioLayout(PrintStream ps, StructNamePrefixer prefixer) {
for (int i = 0; i < bits.size(); i++) {
BitLayout bit = bits.get(i);
ps.print(prefixer.get(bit.name));
ps.print(" = bits, U32, ");
ps.print(this.offset);
ps.print(", [");
ps.print(i + ":" + i);
// TODO: print actual bit options
ps.print("], \"false\", \"true\"");
ps.println();
}
}
@Override
public void writeCLayout(PrintStream ps) {
// always emit all 32 bits
for (int i = 0; i < 32; i++) {
ps.print("\t/**\n\t");
if (i < bits.size()) {
BitLayout bit = this.bits.get(i);
if (bit.comment != null) {
ps.println(" * " + bit.comment.replaceAll("[+]", "").replaceAll(";", "").replace("\\n", "\n\t * "));
ps.print('\t');
}
ps.println("offset " + this.offsetWithinStruct + " bit " + i + " */");
ps.println("\tbool " + bit.name + " : 1;");
} else {
// Force pad out all bit groups to a full 32b/4B
ps.println("offset " + this.offsetWithinStruct + " bit " + i + " */");
ps.println("\tbool unusedBit_" + this.offsetWithinStruct + "_" + i + " : 1;");
}
}
}
}

View File

@ -0,0 +1,58 @@
package com.rusefi.newparse.layout;
import com.rusefi.newparse.parsing.EnumField;
import com.rusefi.newparse.parsing.FieldOptions;
import com.rusefi.newparse.parsing.Type;
import java.io.PrintStream;
public class EnumLayout extends Layout {
private final String name;
private final Type type;
private final String enumType;
private final String values;
private final FieldOptions options;
public EnumLayout(EnumField field) {
this.name = field.name;
this.type = field.type;
this.enumType = field.enumType;
this.values = field.values;
this.options = field.options;
}
@Override
public int getSize() {
return this.type.size;
}
@Override
public void writeTunerstudioLayout(PrintStream ps, StructNamePrefixer prefixer) {
ps.print(prefixer.get(this.name));
ps.print(" = bits, ");
ps.print(this.type.tsType);
ps.print(", ");
ps.print(this.offset);
ps.print(", ");
// TODO: automatically compute number of bits required?
ps.print("[0:7], ");
// TODO: where should value define resolution happen?
ps.print(this.values);
ps.println();
}
@Override
public void writeCLayout(PrintStream ps) {
this.writeCOffsetHeader(ps, this.options.comment, this.options.units);
ps.println("\t" + this.enumType + " " + this.name + ";");
}
@Override
public void writeCLayout(PrintStream ps, int arrayLength) {
this.writeCOffsetHeader(ps, this.options.comment, this.options.units);
ps.println("\t" + this.enumType + " " + this.name + "[" + arrayLength + "];");
}
}

View File

@ -0,0 +1,69 @@
package com.rusefi.newparse.layout;
import java.io.PrintStream;
public abstract class Layout {
public int offset = -1;
public int offsetWithinStruct = -1;
public abstract int getSize();
public int getAlignment() {
// Default to size
return this.getSize();
}
public void setOffset(int offset) {
this.offset = offset;
}
public void setOffsetWithinStruct(int offset) {
offsetWithinStruct = offset;
}
@Override
public String toString() {
return "offset = " + offset + " size = " + this.getSize();
}
public final void writeTunerstudioLayout(PrintStream ps) {
writeTunerstudioLayout(ps, new StructNamePrefixer());
}
public void writeTunerstudioLayout(PrintStream ps, StructNamePrefixer prefixer) {}
public void writeTunerstudioLayout(PrintStream ps, StructNamePrefixer prefixer, int arrayLength) {
throw new IllegalStateException("This type can't be in an array!");
}
protected void writeCOffsetHeader(PrintStream ps, String comment, String units) {
ps.println("\t/**");
if (comment != null) {
comment = comment.replaceAll(";", "");
comment = comment.replaceAll("[+]", "");
comment = comment.replaceAll("\\n", "\n\t * ");
if (comment.length() == 0) {
comment = null;
}
}
if (comment != null) {
comment = comment.replaceAll("\\\\n", "\n\t * ");
ps.println("\t * " + comment);
}
if (units != null && units.length() > 2) {
ps.println("\t" + units.replace("\"", ""));
}
ps.println("\t * offset " + this.offsetWithinStruct);
ps.println("\t */");
}
public void writeCLayout(PrintStream ps) { }
public void writeCLayout(PrintStream ps, int arrayLength) {
throw new IllegalStateException("This type can't be in an array!");
}
}

View File

@ -0,0 +1,73 @@
package com.rusefi.newparse.layout;
import com.rusefi.newparse.parsing.FieldOptions;
import com.rusefi.newparse.parsing.ScalarField;
import com.rusefi.newparse.parsing.Type;
import java.io.PrintStream;
public class ScalarLayout extends Layout {
private String name;
private Type type;
private FieldOptions options;
public ScalarLayout(ScalarField field) {
this.name = field.name;
this.options = field.options;
this.type = field.type;
}
@Override
public int getSize() {
return this.type.size;
}
@Override
public String toString() {
return "Scalar " + type.cType + " " + super.toString();
}
private void printBeforeArrayLength(PrintStream ps, StructNamePrefixer prefixer) {
ps.print(prefixer.get(this.name));
ps.print(" = scalar, ");
ps.print(this.type.tsType);
ps.print(", ");
ps.print(this.offset);
ps.print(", ");
}
private void printAfterArrayLength(PrintStream ps) {
options.printTsFormat(ps);
ps.println();
}
@Override
public void writeTunerstudioLayout(PrintStream ps, StructNamePrefixer prefixer, int arrayLength) {
printBeforeArrayLength(ps, prefixer);
ps.print("[");
ps.print(arrayLength);
ps.print("], ");
printAfterArrayLength(ps);
}
@Override
public void writeTunerstudioLayout(PrintStream ps, StructNamePrefixer prefixer) {
printBeforeArrayLength(ps, prefixer);
printAfterArrayLength(ps);
}
@Override
public void writeCLayout(PrintStream ps) {
this.writeCOffsetHeader(ps, this.options.comment, this.options.units);
ps.println("\t" + this.type.cType.replaceAll("^int32_t$", "int") + " " + this.name + ";");
}
@Override
public void writeCLayout(PrintStream ps, int arrayLength) {
this.writeCOffsetHeader(ps, this.options.comment, this.options.units);
ps.println("\t" + this.type.cType.replaceAll("^int32_t$", "int") + " " + this.name + "[" + arrayLength + "];");
}
}

View File

@ -0,0 +1,55 @@
package com.rusefi.newparse.layout;
import com.rusefi.newparse.parsing.StringField;
import com.rusefi.newparse.parsing.UnusedField;
import java.io.PrintStream;
public class StringLayout extends Layout {
private final String name;
private final int size;
public StringLayout(StringField field) {
this.name = field.name;
this.size = field.size;
}
@Override
public int getSize() {
return this.size;
}
@Override
public int getAlignment() {
// char can be single aligned
return 1;
}
@Override
public String toString() {
return "String " + super.toString();
}
@Override
public void writeTunerstudioLayout(PrintStream ps, StructNamePrefixer prefixer) {
ps.print(prefixer.get(this.name));
ps.print(" = scalar, ASCII, ");
ps.print(this.offset);
ps.print(", ");
ps.print(size);
ps.println();
}
@Override
public void writeCLayout(PrintStream ps) {
this.writeCOffsetHeader(ps, null, null);
ps.println("\tchar " + this.name + "[" + this.size + "];");
}
@Override
public void writeCLayout(PrintStream ps, int arrayLength) {
this.writeCOffsetHeader(ps, null, null);
ps.println("\tchar " + this.name + "[" + arrayLength + "][" + this.size + "];");
}
}

View File

@ -0,0 +1,204 @@
package com.rusefi.newparse.layout;
import com.rusefi.newparse.parsing.*;
import java.io.PrintStream;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;
public class StructLayout extends Layout {
/*private*/public List<Layout> children = new ArrayList<>();
public final String typeName;
private final String name;
private final String comment;
private final Boolean noPrefix;
private final int size;
private static int getAlignedOffset(int offset, int alignment) {
// Align each element to its own size
if ((offset % alignment) != 0) {
return offset + alignment - (offset % alignment);
} else {
return offset;
}
}
int padOffsetWithUnused(int offset, int align) {
int alignedOffset = getAlignedOffset(offset, align);
int needsUnused = alignedOffset - offset;
if (needsUnused > 0) {
UnusedLayout ul = new UnusedLayout(needsUnused);
ul.setOffset(offset);
ul.setOffsetWithinStruct(offset - this.offset);
children.add(ul);
return alignedOffset;
}
return offset;
}
public StructLayout(int offset, String name, Struct parsedStruct) {
setOffset(offset);
this.typeName = parsedStruct.name;
this.name = name;
this.comment = parsedStruct.comment;
this.noPrefix = parsedStruct.noPrefix;
int initialOffest = offset;
for (Field f : parsedStruct.fields) {
if (f instanceof ArrayField) {
ArrayField asf = (ArrayField)f;
// If not a scalar, you must iterate
assert(asf.prototype instanceof ScalarField || asf.iterate);
if (asf.iterate) {
if (asf.prototype instanceof StructField) {
// Struct: special case of a struct array
offset = addItem(offset, new ArrayIterateStructLayout((StructField)asf.prototype, asf.length));
} else {
// array of scalars (or enums)
offset = addItem(offset, new ArrayIterateScalarLayout(asf.prototype, asf.length));
}
} else /* not iterate */ {
// If not a scalar, you must iterate
assert(asf.prototype instanceof ScalarField);
ScalarField prototype = (ScalarField)asf.prototype;
offset = addItem(offset, new ArrayLayout(prototype, asf.length));
}
} else {
offset = addItem(offset, f);
}
}
// Structs are always a multiple of 4 bytes long, pad the end appropriately
offset = padOffsetWithUnused(offset, 4);
size = offset - initialOffest;
}
private int addItem(int offset, Field f) {
if (f instanceof StructField) {
// Special case for structs - we have to compute base offset first
StructField sf = (StructField) f;
return addStruct(offset, sf.struct, sf.name);
}
Layout l = null;
if (f instanceof ScalarField) {
l = new ScalarLayout((ScalarField)f);
} else if (f instanceof EnumField) {
l = new EnumLayout((EnumField)f);
} else if (f instanceof UnusedField) {
l = new UnusedLayout((UnusedField) f);
} else if (f instanceof BitGroup) {
l = new BitGroupLayout((BitGroup) f);
} else if (f instanceof StringField) {
l = new StringLayout((StringField) f);
} else if (f instanceof Union) {
l = new UnionLayout((Union)f);
} else {
throw new RuntimeException("unexpected field type during layout");
}
return addItem(offset, l);
}
private int addItem(int offset, Layout l) {
// Slide the offset up by the required alignment of this element
offset = padOffsetWithUnused(offset, l.getAlignment());
// place the element
l.setOffset(offset);
l.setOffsetWithinStruct(offset - this.offset);
children.add(l);
return offset + l.getSize();
}
private int addStruct(int offset, Struct struct, String name) {
offset = padOffsetWithUnused(offset, 4);
// Recurse and build this new struct
StructLayout sl = new StructLayout(offset, name, struct);
sl.setOffsetWithinStruct(offset - this.offset);
this.children.add(sl);
// Update offset with the struct size - it's guaranteed to be a multiple of 4 bytes
int structSize = sl.getSize();
return offset + structSize;
}
@Override
public int getSize() {
return this.size;
}
@Override
public int getAlignment() {
// All structs should be aligned on a 4 byte boundary
return 4;
}
@Override
public String toString() {
return "Struct " + this.typeName + " " + super.toString();
}
@Override
public void writeTunerstudioLayout(PrintStream ps, StructNamePrefixer prefixer) {
if (!this.noPrefix) {
ps.println("; start struct " + this.typeName);
prefixer.push(this.name);
}
// print all children in sequence
this.children.forEach(c -> c.writeTunerstudioLayout(ps, prefixer));
if (!this.noPrefix) {
prefixer.pop();
}
if (!this.noPrefix) {
ps.println("; end struct " + this.typeName);
}
}
@Override
public void writeCLayout(PrintStream ps) {
this.writeCOffsetHeader(ps, null, null);
ps.println("\t" + this.typeName + " " + this.name + ";");
}
@Override
public void writeCLayout(PrintStream ps, int arrayLength) {
this.writeCOffsetHeader(ps, null, null);
ps.println("\t" + this.typeName + " " + this.name + "[" + arrayLength + "];");
}
public void writeCLayoutRoot(PrintStream ps) {
if (this.comment != null) {
ps.println("/**\n * @brief " + this.comment);
ps.println("*/");
}
ps.println("// start of " + this.typeName);
ps.println("struct " + this.typeName + " {");
this.children.forEach(c -> c.writeCLayout(ps));
ps.println("\t/** total size " + getSize() + "*/");
ps.println("};");
ps.println();
}
}

View File

@ -0,0 +1,30 @@
package com.rusefi.newparse.layout;
import java.util.Stack;
import java.util.stream.Collectors;
public class StructNamePrefixer {
private Stack<String> stack = new Stack<>();
public void pop() {
stack.pop();
}
public void push(String name) {
stack.push(name + "_");
}
private String suffix = new String();
public void setSuffix(String suffix) {
this.suffix = suffix;
}
public void resetSuffix() {
this.suffix = new String();
}
String get(String name) {
return stack.stream().collect(Collectors.joining()) + name + suffix;
}
}

View File

@ -0,0 +1,73 @@
package com.rusefi.newparse.layout;
import com.rusefi.newparse.parsing.ArrayField;
import com.rusefi.newparse.parsing.Field;
import com.rusefi.newparse.parsing.ScalarField;
import com.rusefi.newparse.parsing.Union;
import java.io.PrintStream;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;
public class UnionLayout extends Layout {
private List<Layout> children = new ArrayList<>();
public UnionLayout(Union u) {
for (Field f : u.fields) {
// For every child, check if it is the largest, and grow if so
if (f instanceof ArrayField) {
ArrayField af = (ArrayField)f;
// we probably don't need union of iterate?
assert(!af.iterate);
ScalarField prototype = (ScalarField)af.prototype;
this.children.add(new ArrayLayout(prototype, af.length));
} else if (f instanceof ScalarField) {
this.children.add(new ScalarLayout((ScalarField)f));
} else {
throw new RuntimeException("Tried to create union with member type " + f.getClass().getSimpleName());
}
}
}
@Override
public void setOffset(int offset) {
super.setOffset(offset);
this.children.stream().forEach(c -> c.setOffset(offset));
}
@Override
public void setOffsetWithinStruct(int offset) {
super.setOffsetWithinStruct(offset);
this.children.stream().forEach(c -> c.setOffsetWithinStruct(offset));
}
@Override
public int getSize() {
return this.children.stream().map(l -> l.getSize()).max(Integer::compare).get();
}
@Override
public int getAlignment() {
// The alignment of the union is the largest alignment required by one of the members
return this.children.stream().map(l -> l.getAlignment()).max(Integer::compare).get();
}
@Override
public void writeTunerstudioLayout(PrintStream ps, StructNamePrefixer prefixer) {
// Simply write out all children - no container necessary as fields can overlap in TS
this.children.forEach(c -> c.writeTunerstudioLayout(ps, prefixer));
}
@Override
public void writeCLayout(PrintStream ps) {
this.writeCOffsetHeader(ps, "union size " + this.getSize() + ", " + this.children.size() + " members", null);
// emit an anonymous union that contains all our members
ps.println("\tunion {");
this.children.forEach(c -> c.writeCLayout(ps));
ps.println("\t};");
}
}

View File

@ -0,0 +1,46 @@
package com.rusefi.newparse.layout;
import com.rusefi.newparse.parsing.EnumField;
import com.rusefi.newparse.parsing.Type;
import com.rusefi.newparse.parsing.UnusedField;
import java.io.PrintStream;
import java.util.Random;
public class UnusedLayout extends Layout {
private final int size;
public UnusedLayout(int size) {
this.size = size;
}
public UnusedLayout(UnusedField field) {
this.size = field.size;
}
@Override
public int getSize() {
return this.size;
}
@Override
public int getAlignment() {
return 1;
}
@Override
public String toString() {
return "Unused " + super.toString();
}
@Override
public void writeTunerstudioLayout(PrintStream ps, StructNamePrefixer prefixer) {
ps.println("; unused " + this.size + " bytes at offset " + this.offset);
}
@Override
public void writeCLayout(PrintStream ps) {
this.writeCOffsetHeader(ps, null, null);
ps.println("\tchar unused" + this.offsetWithinStruct + "[" + this.size + "];");
}
}

View File

@ -0,0 +1,11 @@
package com.rusefi.newparse.parsing;
import java.util.List;
public class Union implements Field {
public final List<Field> fields;
public Union(List<Field> fields) {
this.fields = fields;
}
}