เป็นไปได้ไหมที่ yylval จะเป็น struct แทนที่จะเป็น union?

บน Bison เป็นไปได้ไหมที่ yylval จะเป็น struct แทนที่จะเป็น union ? ฉันรู้ว่าฉันสามารถกำหนด yylval ให้เป็น union ด้วย %union{} ได้ แต่มีวิธีกำหนด yylval เป็น struct หรือไม่ เพื่อส่งคืนบรรทัดและสตริงของตัวระบุสำหรับตัวอย่างและเข้าถึงข้อมูลเหล่านี้เกี่ยวกับการกระทำของกฎไวยากรณ์บางอย่างเกี่ยวกับวัวกระทิง


person Joao Pedro    schedule 25.11.2018    source แหล่งที่มา


คำตอบ (2)


ใช่ คุณสามารถ #define YYSTYPE เป็นประเภทใดก็ได้ที่คุณต้องการ แทนที่จะใช้ %union อย่างไรก็ตาม การทำเช่นนั้นไม่ค่อยมีประโยชน์1 -- หากคุณต้องการข้อมูลตำแหน่งแหล่งที่มา คุณควรใช้ %position ร่วมกับ %union จะดีกว่ามาก

นอกจากนี้ยังเป็นไปได้ (และทั่วไป) ที่จะใช้ structs ภายใน การประกาศ %union ซึ่งช่วยให้กฎบางข้อส่งกลับค่าหลายค่าได้ง่าย (อย่างมีประสิทธิภาพ)


1ปัญหาหลักคือ หากคุณใช้ %type เพื่อระบุการใช้ฟิลด์ struct หนึ่งฟิลด์ การใช้ฟิลด์อื่นในการดำเนินการเดียวกันจะยุ่งยาก คุณต้องทำทุกอย่างด้วยตนเอง ซึ่งจะทำให้เสียประโยชน์จากการตรวจสอบประเภทสหภาพของวัวกระทิง

person Chris Dodd    schedule 25.11.2018

หากคุณต้องการเก็บข้อมูลตำแหน่ง (หมายเลขบรรทัดและหมายเลขคอลัมน์) สำหรับโทเค็นของคุณ คุณสามารถใช้เครื่องมืออำนวยความสะดวกตำแหน่งของ 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;                            \
  }
%}
person rici    schedule 26.11.2018
comment
ฉันต้องการบันทึกทั้ง yytext และจำนวนเต็มโทเค็นเป็น yylval เช่น #define YYSTYPE struct { int token; char *literal }; เป็นไปได้ไหม - person linrongbin; 08.01.2020
comment
@linrongbin: แน่นอน อย่าใช้ #define YYSTYPE แต่; นั่นจะทำให้คุณเดือดร้อนอย่างแน่นอน คุณต้องตรวจสอบให้แน่ใจว่าประกาศมองเห็นได้ทุกที่ที่จำเป็น ซึ่งหมายความว่าควรอยู่ในส่วนหัวที่สร้างโดยวัวกระทิง เพื่อให้บรรลุเป้าหมายดังกล่าว ให้ใส่การประกาศ struct (struct MyToken { ... }) ลงในบล็อก code requires ในคำจำกัดความของวัวกระทิงของคุณ จากนั้นใช้ %define api.value.type {struct MyToken} ตามที่อธิบายไว้ใน คู่มือวัวกระทิง หากคุณต้องการคำตอบที่ละเอียดกว่านี้ ให้ถามคำถามใหม่ - person rici; 08.01.2020