@@ -424,7 +424,19 @@ def pslr_function_declarations
424424
425425 if pslr_scanner_enabled?
426426 declarations << <<~C_CODE
427+ #ifndef YYPSLR_SCAN_RESULT_DEFINED
428+ # define YYPSLR_SCAN_RESULT_DEFINED
429+ typedef struct yypslr_scan_result {
430+ int token;
431+ int length;
432+ int is_layout;
433+ int is_character_token;
434+ } yypslr_scan_result;
435+ #endif
436+
437+ int yy_pseudo_scan_result (int parser_state, const char *input, yypslr_scan_result *result);
427438 int yy_pseudo_scan (int parser_state, const char *input, int *match_length);
439+ int yy_pslr_token_is_layout (int token);
428440 C_CODE
429441
430442 declarations << <<~C_CODE
@@ -435,6 +447,15 @@ def pslr_function_declarations
435447 # define YYPSLR_PSEUDO_SCAN_STATE(ParserState, Input, MatchLength) \\
436448 yy_pseudo_scan ((ParserState), (Input), (MatchLength))
437449 #endif
450+
451+ #ifndef YYPSLR_PSEUDO_SCAN_RESULT_STATE
452+ # define YYPSLR_PSEUDO_SCAN_RESULT_STATE(ParserState, Input, Result) \\
453+ yy_pseudo_scan_result ((ParserState), (Input), (Result))
454+ #endif
455+
456+ #ifndef YYPSLR_TOKEN_IS_LAYOUT
457+ # define YYPSLR_TOKEN_IS_LAYOUT(Token) yy_pslr_token_is_layout ((Token))
458+ #endif
438459 C_CODE
439460 end
440461
@@ -453,6 +474,13 @@ def pslr_function_declarations
453474 ? YYPSLR_PSEUDO_SCAN_STATE (YYGETSTATE_CONTEXT (Context), (Input), (MatchLength)) \\
454475 : YYEMPTY)
455476 #endif
477+
478+ #ifndef YYPSLR_PSEUDO_SCAN_RESULT
479+ # define YYPSLR_PSEUDO_SCAN_RESULT(Context, Input, Result) \\
480+ ((Context) != 0 \\
481+ ? YYPSLR_PSEUDO_SCAN_RESULT_STATE (YYGETSTATE_CONTEXT (Context), (Input), (Result)) \\
482+ : YYEMPTY)
483+ #endif
456484 C_CODE
457485 end
458486
@@ -549,6 +577,20 @@ def token_pattern_token_ids_table
549577 lines << "static const int yy_token_pattern_to_token_id[YY_NUM_TOKEN_PATTERNS] = {"
550578 lines << " #{ @context . states . token_patterns . map { |token_pattern | pslr_token_id ( token_pattern ) } . join ( ', ' ) } "
551579 lines << "};"
580+ lines << ""
581+ lines << "static const int yy_token_pattern_is_layout[YY_NUM_TOKEN_PATTERNS] = {"
582+ lines << " #{ @context . states . token_patterns . map { |token_pattern | token_pattern . layout? ? 1 : 0 } . join ( ', ' ) } "
583+ lines << "};"
584+ lines << ""
585+ lines << "int"
586+ lines << "yy_pslr_token_is_layout (int token)"
587+ lines << "{"
588+ lines << " int i;"
589+ lines << " for (i = 0; i < YY_NUM_TOKEN_PATTERNS; i++)"
590+ lines << " if (yy_token_pattern_to_token_id[i] == token)"
591+ lines << " return yy_token_pattern_is_layout[i];"
592+ lines << " return 0;"
593+ lines << "}"
552594 lines . join ( "\n " )
553595 end
554596
@@ -617,6 +659,14 @@ def scanner_accepts_table_code
617659 end
618660
619661 lines << "};"
662+ lines << ""
663+ lines << "static const int yy_scanner_fallback_accepts[YY_NUM_ACCEPTING_STATES] = {"
664+ fallback_row = pslr_accepting_states . map do |fsa_state |
665+ token = scanner_accepts . fallback_table [ fsa_state . id ]
666+ token ? token_pattern_indexes . fetch ( token ) : -1
667+ end
668+ lines << " #{ fallback_row . join ( ', ' ) } "
669+ lines << "};"
620670 end
621671
622672 lines . join ( "\n " )
@@ -651,6 +701,95 @@ def length_precedences_table_code
651701 lines . join ( "\n " )
652702 end
653703
704+ def pslr_lac_function
705+ return "" unless pslr_enabled?
706+
707+ <<~C_CODE
708+
709+ static int
710+ yy_lac_check_ (yy_state_t *yyss, yy_state_t *yyssp, yysymbol_kind_t yytoken)
711+ {
712+ YYPTRDIFF_T yylac_len = yyssp - yyss + 1;
713+ yy_state_t *yylac_base = YY_CAST (yy_state_t *,
714+ YYMALLOC (YY_CAST (YYSIZE_T, YYMAXDEPTH * YYSIZEOF (yy_state_t))));
715+ yy_state_t *yylac_top;
716+
717+ if (!yylac_base)
718+ return 1;
719+
720+ if (YYMAXDEPTH < yylac_len)
721+ {
722+ YYFREE (yylac_base);
723+ return 1;
724+ }
725+
726+ YYCOPY (yylac_base, yyss, yylac_len);
727+ yylac_top = yylac_base + yylac_len - 1;
728+
729+ for (;;)
730+ {
731+ int yystate = *yylac_top;
732+ int yyn = yypact[yystate];
733+
734+ if (!yypact_value_is_default (yyn))
735+ {
736+ yyn += yytoken;
737+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == yytoken)
738+ {
739+ yyn = yytable[yyn];
740+ if (0 < yyn)
741+ {
742+ YYFREE (yylac_base);
743+ return 1;
744+ }
745+ if (yytable_value_is_error (yyn))
746+ {
747+ YYFREE (yylac_base);
748+ return 0;
749+ }
750+ yyn = -yyn;
751+ }
752+ else
753+ {
754+ yyn = yydefact[yystate];
755+ if (yyn == 0)
756+ {
757+ YYFREE (yylac_base);
758+ return 0;
759+ }
760+ }
761+ }
762+ else
763+ {
764+ yyn = yydefact[yystate];
765+ if (yyn == 0)
766+ {
767+ YYFREE (yylac_base);
768+ return 0;
769+ }
770+ }
771+
772+ yylac_top -= yyr2[yyn];
773+ {
774+ const int yylhs = yyr1[yyn] - YYNTOKENS;
775+ const int yyi = yypgoto[yylhs] + *yylac_top;
776+ yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yylac_top
777+ ? yytable[yyi]
778+ : yydefgoto[yylhs]);
779+ }
780+
781+ if (yylac_base + YYMAXDEPTH - 1 <= yylac_top)
782+ {
783+ YYFREE (yylac_base);
784+ return 1;
785+ }
786+
787+ *++yylac_top = YY_CAST (yy_state_t, yystate);
788+ }
789+ }
790+ C_CODE
791+ end
792+
654793 # Generate pseudo_scan function as C code
655794 def pseudo_scan_function
656795 return "" unless pslr_scanner_enabled?
@@ -666,27 +805,36 @@ def pseudo_scan_function
666805 * input: Input buffer pointer
667806 * match_length: Output parameter for matched length
668807 *
669- * Returns: Selected parser token ID, or YYEMPTY if no match
808+ * Returns: Selected parser token ID. If neither the parser-state row
809+ * nor fallback row matches, returns YYUNDEF and consumes one byte.
670810 */
671811 int
672- yy_pseudo_scan (int parser_state, const char *input, int *match_length )
812+ yy_pseudo_scan_result (int parser_state, const char *input, yypslr_scan_result *result )
673813 {
674- int local_match_length = 0;
675814 int ss = 0; /* FSA initial state */
676815 int ibest = 0;
677816 int pbest = YY_PSLR_EMPTY_PATTERN;
817+ int fallback_ibest = 0;
818+ int fallback_pbest = YY_PSLR_EMPTY_PATTERN;
678819 int i = 0;
679820
680- if (match_length == NULL) {
681- match_length = &local_match_length ;
821+ if (result == NULL) {
822+ return YYEMPTY ;
682823 }
683824
684- *match_length = 0;
825+ result->token = YYEMPTY;
826+ result->length = 0;
827+ result->is_layout = 0;
828+ result->is_character_token = 0;
685829
686830 if (parser_state < 0 || parser_state >= YY_NUM_PARSER_STATES || input == NULL) {
687831 return YYEMPTY;
688832 }
689833
834+ if (input[0] == '\\ 0') {
835+ return YYEMPTY;
836+ }
837+
690838 while (input[i] != '\\ 0') {
691839 int c = (unsigned char)input[i];
692840 int next_ss = yy_scanner_transition[ss][c];
@@ -709,15 +857,46 @@ def pseudo_scan_function
709857 ibest = i;
710858 }
711859 }
860+
861+ pattern_index = yy_scanner_fallback_accepts[sa];
862+ if (pattern_index != YY_PSLR_EMPTY_PATTERN) {
863+ fallback_pbest = pattern_index;
864+ fallback_ibest = i;
865+ }
712866 }
713867 }
714868
715- *match_length = ibest;
716- if (pbest == YY_PSLR_EMPTY_PATTERN) {
717- return YYEMPTY;
869+ if (pbest != YY_PSLR_EMPTY_PATTERN) {
870+ result->token = yy_token_pattern_to_token_id[pbest];
871+ result->length = ibest;
872+ result->is_layout = yy_token_pattern_is_layout[pbest];
873+ return result->token;
874+ }
875+
876+ if (fallback_pbest != YY_PSLR_EMPTY_PATTERN) {
877+ result->token = yy_token_pattern_to_token_id[fallback_pbest];
878+ result->length = fallback_ibest;
879+ result->is_layout = yy_token_pattern_is_layout[fallback_pbest];
880+ return result->token;
881+ }
882+
883+ result->token = YYUNDEF;
884+ result->length = 1;
885+ result->is_character_token = 1;
886+ return result->token;
887+ }
888+
889+ int
890+ yy_pseudo_scan(int parser_state, const char *input, int *match_length)
891+ {
892+ yypslr_scan_result result;
893+ int token = yy_pseudo_scan_result (parser_state, input, &result);
894+
895+ if (match_length != NULL) {
896+ *match_length = result.length;
718897 }
719898
720- return yy_token_pattern_to_token_id[pbest] ;
899+ return token ;
721900 }
722901 C_CODE
723902 end
0 commit comments