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}