บน Bison เป็นไปได้ไหมที่ yylval จะเป็น struct แทนที่จะเป็น union ? ฉันรู้ว่าฉันสามารถกำหนด yylval ให้เป็น union ด้วย %union{}
ได้ แต่มีวิธีกำหนด yylval เป็น struct หรือไม่ เพื่อส่งคืนบรรทัดและสตริงของตัวระบุสำหรับตัวอย่างและเข้าถึงข้อมูลเหล่านี้เกี่ยวกับการกระทำของกฎไวยากรณ์บางอย่างเกี่ยวกับวัวกระทิง
เป็นไปได้ไหมที่ yylval จะเป็น struct แทนที่จะเป็น union?
คำตอบ (2)
ใช่ คุณสามารถ #define YYSTYPE
เป็นประเภทใดก็ได้ที่คุณต้องการ แทนที่จะใช้ %union
อย่างไรก็ตาม การทำเช่นนั้นไม่ค่อยมีประโยชน์1 -- หากคุณต้องการข้อมูลตำแหน่งแหล่งที่มา คุณควรใช้ %position
ร่วมกับ %union
จะดีกว่ามาก
นอกจากนี้ยังเป็นไปได้ (และทั่วไป) ที่จะใช้ structs ภายใน การประกาศ %union
ซึ่งช่วยให้กฎบางข้อส่งกลับค่าหลายค่าได้ง่าย (อย่างมีประสิทธิภาพ)
1ปัญหาหลักคือ หากคุณใช้ %type
เพื่อระบุการใช้ฟิลด์ struct หนึ่งฟิลด์ การใช้ฟิลด์อื่นในการดำเนินการเดียวกันจะยุ่งยาก คุณต้องทำทุกอย่างด้วยตนเอง ซึ่งจะทำให้เสียประโยชน์จากการตรวจสอบประเภทสหภาพของวัวกระทิง
หากคุณต้องการเก็บข้อมูลตำแหน่ง (หมายเลขบรรทัดและหมายเลขคอลัมน์) สำหรับโทเค็นของคุณ คุณสามารถใช้เครื่องมืออำนวยความสะดวกตำแหน่งของ Bison ซึ่งจะเก็บวัตถุตำแหน่งสำหรับแต่ละโทเค็นและไม่ใช่เทอร์มินัลแยกจากค่าความหมาย ในการดำเนินการ คุณอ้างถึงตำแหน่งของสัญลักษณ์เป็น @n
กลุ่มตำแหน่งจะถูกสร้างขึ้นและดูแลรักษาโดยอัตโนมัติโดยวัวกระทิง หากพบว่าคุณได้อ้างอิงไปยังตำแหน่งใดๆ ในกฎ
ตามค่าเริ่มต้น ประเภทข้อมูลตำแหน่งจะเป็น:
typedef struct YYLTYPE {
int first_line;
int first_column;
int last_line;
int last_column;
} YYLTYPE;
ข้อมูลตำแหน่งสำหรับโทเค็นจะต้องตั้งค่าโดย lexer หากคุณใช้ API เริ่มต้น API ดังกล่าวจะถูกจัดเก็บไว้ในตัวแปรโกลบอล yylloc
parser จะสร้างข้อมูลตำแหน่งสำหรับผู้ที่ไม่ใช่เทอร์มินัลโดยใช้ช่วงจากจุดเริ่มต้นของรายการแรกของการผลิตจนถึงจุดสิ้นสุดของรายการสุดท้าย (สำหรับการผลิตที่ว่างเปล่า จะมีการสร้างออบเจ็กต์ตำแหน่งที่มีความยาวเป็นศูนย์ โดยเริ่มต้นและสิ้นสุดด้วยตำแหน่งเริ่มต้นของโทเค็น lookahead)
ค่าเริ่มต้นทั้งสองนี้สามารถแทนที่ได้หากจำเป็น ดูรายละเอียดในคู่มือ Bison
Flex จะติดตามหมายเลขบรรทัดหากถูกถามด้วย %option yylineno
แต่จะไม่ติดตามตำแหน่งคอลัมน์ ซึ่งค่อนข้างน่ารำคาญ นอกจากนี้ yylloc
ต้องใช้ทั้งหมายเลขบรรทัดเริ่มต้นและสิ้นสุด yylineno
ในการดำเนินการแบบยืดหยุ่นจะเป็นหมายเลขบรรทัดที่ท้ายโทเค็น โดยทั่วไป คุณจะใช้มาโคร YY_USER_ACTION
เพื่อรักษาค่าของ yylloc
; ตัวอย่างการใช้งาน (นำมาจาก คำตอบนี้ ซึ่งคุณควรอ่านหากคุณใช้รหัสนี้) คือ:
%option yylineno
%{
#define YY_USER_ACTION \
yylloc.first_line = yylloc.last_line; \
yylloc.first_column = yylloc.last_column; \
if (yylloc.first_line == yylineno) \
yylloc.last_column += yyleng; \
else { \
int col; \
for (col = 1; yytext[yyleng - col] != '\n'; ++col) {} \
yylloc.last_column = col; \
yylloc.last_line = yylineno; \
}
%}
#define YYSTYPE struct { int token; char *literal };
เป็นไปได้ไหม
- person linrongbin; 08.01.2020
#define YYSTYPE
แต่; นั่นจะทำให้คุณเดือดร้อนอย่างแน่นอน คุณต้องตรวจสอบให้แน่ใจว่าประกาศมองเห็นได้ทุกที่ที่จำเป็น ซึ่งหมายความว่าควรอยู่ในส่วนหัวที่สร้างโดยวัวกระทิง เพื่อให้บรรลุเป้าหมายดังกล่าว ให้ใส่การประกาศ struct
(struct MyToken { ... }
) ลงในบล็อก code requires
ในคำจำกัดความของวัวกระทิงของคุณ จากนั้นใช้ %define api.value.type {struct MyToken}
ตามที่อธิบายไว้ใน คู่มือวัวกระทิง หากคุณต้องการคำตอบที่ละเอียดกว่านี้ ให้ถามคำถามใหม่
- person rici; 08.01.2020