github.com/yanyiwu/go@v0.0.0-20150106053140-03d6637dbb7f/src/cmd/gc/bisonerrors (about)

     1  #!/usr/bin/awk -f
     2  # Copyright 2010 The Go Authors.  All rights reserved.
     3  # Use of this source code is governed by a BSD-style
     4  # license that can be found in the LICENSE file.
     5  
     6  # This program implements the core idea from
     7  #
     8  #	Clinton L. Jeffery, Generating LR syntax error messages from examples,
     9  #	ACM TOPLAS 25(5) (September 2003).  http://doi.acm.org/10.1145/937563.937566
    10  # 
    11  # It reads Bison's summary of a grammar followed by a file
    12  # like go.errors, replacing lines beginning with % by the 
    13  # yystate and yychar that will be active when an error happens
    14  # while parsing that line.  
    15  #
    16  # Unlike the system described in the paper, the lines in go.errors
    17  # give grammar symbol name lists, not actual program fragments.
    18  # This is a little less programmer-friendly but doesn't require being
    19  # able to run the text through lex.c.
    20  
    21  BEGIN{
    22  	bison = 1
    23  	grammar = 0
    24  	states = 0
    25  	open = 0
    26  }
    27  
    28  # In Grammar section of y.output,
    29  # record lhs and length of rhs for each rule.
    30  bison && /^Grammar/ { grammar = 1 }
    31  bison && /^(Terminals|state 0)/ { grammar = 0 }
    32  grammar && NF>0 {
    33  	if($2 != "|") {
    34  		r = $2
    35  		sub(/:$/, "", r)
    36  	}
    37  	rulelhs[$1] = r
    38  	rulesize[$1] = NF-2
    39  	if(rulesize[$1] == 1 && $3 == "%empty") {
    40  		rulesize[$1] = 0
    41  	}
    42  	if(rulesize[$1] == 3 && $3 $4 $5 == "/*empty*/") {
    43  		rulesize[$1] = 0
    44  	}
    45  }
    46  
    47  # In state dumps, record shift/reduce actions.
    48  bison && /^[Ss]tate 0/ { grammar = 0; states = 1 }
    49  
    50  states && /^[Ss]tate / { state = $2 }
    51  states { statetext[state] = statetext[state] $0 "\n" }
    52  
    53  states && / shift/ {
    54  	n = nshift[state]++
    55  	if($0 ~ /and go to/)
    56  		shift[state,n] = $7 # GNU Bison
    57  	else
    58  		shift[state,n] = $3 # Plan 9 Yacc
    59  	shifttoken[state,n] = $1
    60  	next
    61  }
    62  states && / (go to|goto)/ {
    63  	n = nshift[state]++
    64  	if($0 ~ /go to/)
    65  		shift[state,n] = $5 # GNU Bison
    66  	else
    67  		shift[state,n] = $3 # Plan 9 Yacc
    68  	shifttoken[state,n] = $1
    69  	next
    70  }
    71  states && / reduce/ {
    72  	n = nreduce[state]++
    73  	if($0 ~ /reduce using rule/)
    74  		reduce[state,n] = $5 # GNU Bison
    75  	else
    76  		reduce[state,n] = $3 # Plan 9 yacc
    77  	reducetoken[state,n] = $1
    78  	next
    79  }
    80  
    81  # Skip over the summary information printed by Plan 9 yacc.
    82  /nonterminals$/,/^maximum spread/ { next }
    83  
    84  # First // comment marks the beginning of the pattern file.
    85  /^\/\// { bison = 0; grammar = 0; state = 0 }
    86  bison { next }
    87  
    88  # Treat % as first field on line as introducing a pattern (token sequence).
    89  # Run it through the LR machine and print the induced "yystate, yychar,"
    90  # at the point where the error happens.
    91  $1 == "%" {
    92  	nstack = 0
    93  	state = 0
    94  	f = 2
    95  	tok = ""
    96  	for(;;) {
    97  		if(tok == "" && f <= NF) {
    98  			tok = $f
    99  			f++
   100  		}
   101  		found = 0
   102  		for(j=0; j<nshift[state]; j++) {
   103  			if(shifttoken[state,j] == tok) {
   104  				# print "SHIFT " tok " " state " -> " shift[state,j]
   105  				stack[nstack++] = state
   106  				state = shift[state,j]
   107  				found = 1
   108  				tok = ""
   109  				break
   110  			}
   111  		}
   112  		if(found)
   113  			continue
   114  		for(j=0; j<nreduce[state]; j++) {
   115  			t = reducetoken[state,j]
   116  			if(t == tok || t == "$default" || t == ".") {
   117  				stack[nstack++] = state
   118  				rule = reduce[state,j]
   119  				nstack -= rulesize[rule]
   120  				state = stack[--nstack]
   121  				lhs = rulelhs[rule]
   122  				if(tok != "")
   123  					--f
   124  				tok = rulelhs[rule]
   125  				# print "REDUCE " nstack " " state " " tok " rule " rule " size " rulesize[rule]
   126  				found = 1
   127  				break
   128  			}
   129  		}
   130  		if(found)
   131  			continue
   132  
   133  		# No shift or reduce applied - found the error.
   134  		printf("\t{%s, %s,\n", state, tok);
   135  		open = 1;
   136  		break
   137  	}
   138  	next
   139  }
   140  
   141  # Print other lines verbatim.
   142  open && /,$/ {
   143  	s = $0;
   144  	sub(",", "},", s)
   145  	print s
   146  	open = 0
   147  	next
   148  }
   149  
   150  open && /"$/ {
   151  	print $0 "}"
   152  	open = 0
   153  	next
   154  }
   155  
   156  {print}