@@ -28,9 +28,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
28
*/
29
29
30
30
%{
31
- package gyp
31
+ package parser
32
32
33
33
import (
34
+ " fmt"
35
+ " io"
36
+ " io/ioutil"
34
37
" strings"
35
38
" github.com/VirusTotal/gyp/ast"
36
39
gyperror " github.com/VirusTotal/gyp/error"
@@ -55,6 +58,93 @@ type stringModifiers struct {
55
58
XorMax int32
56
59
}
57
60
61
+ // Lexer is an adapter that fits the flexgo lexer ("Scanner") into goyacc
62
+ type lexer struct {
63
+ scanner Scanner
64
+ err gyperror.Error
65
+ ruleSet *ast.RuleSet
66
+ }
67
+
68
+ // Lex provides the interface expected by the goyacc parser.
69
+ // It sets the context's lval pointer (defined in the lexer file)
70
+ // to the one passed as an argument so that the parser actions
71
+ // can make use of it.
72
+ func (l *lexer) Lex(lval *yrSymType) int {
73
+ l.scanner .Context .lval = lval
74
+ r := l.scanner .Lex ()
75
+ if r.Error .Code != 0 {
76
+ r.Error .Line = l.scanner .Lineno
77
+ panic (r.Error )
78
+ }
79
+ return r.Token
80
+ }
81
+
82
+ // Error satisfies the interface expected of the goyacc parser.
83
+ func (l *lexer) Error(msg string) {
84
+ l.err = gyperror.Error {
85
+ Code: gyperror.LexicalError ,
86
+ Line: l.scanner .Lineno ,
87
+ Message: msg,
88
+ }
89
+ }
90
+
91
+ // setError sets the lexer error. The error message can be built by passing
92
+ // a format string and arguments as fmt.Sprintf. This function returns 1 as
93
+ // it's intended to be used by Parse as:
94
+ // return lexer.setError(...)
95
+ // By returning 1 from Parse the parsing is aborted.
96
+ func (l *lexer) setError(code gyperror.Code, format string, a ...interface{}) int {
97
+ l.err = gyperror.Error {
98
+ Code: code,
99
+ Line: l.scanner .Lineno ,
100
+ Message: fmt.Sprintf (format, a...),
101
+ }
102
+ return 1
103
+ }
104
+
105
+
106
+ // Helper function that casts a yrLexer interface to a lexer struct.
107
+ func asLexer (l yrLexer) *lexer {
108
+ return l.(*lexer)
109
+ }
110
+
111
+
112
+ func Parse (input io.Reader) (rs *ast.RuleSet, err error) {
113
+ defer func () {
114
+ if r := recover (); r != nil {
115
+ if yaraError, ok := r.(gyperror.Error ); ok {
116
+ err = yaraError
117
+ } else {
118
+ err = gyperror.Error {
119
+ Code: gyperror.UnknownError ,
120
+ Message: fmt.Sprintf (" %v" , r),
121
+ }
122
+ }
123
+ }
124
+ }()
125
+
126
+ lexer := &lexer{
127
+ scanner: *NewScanner (),
128
+ ruleSet: &ast.RuleSet {
129
+ Imports: make ([]string, 0 ),
130
+ Rules: make ([]*ast.Rule , 0 ),
131
+ },
132
+ }
133
+ lexer.scanner .In = input
134
+ lexer.scanner .Out = ioutil.Discard
135
+
136
+ if result := yrParse (lexer); result != 0 {
137
+ err = lexer.err
138
+ }
139
+
140
+ return lexer.ruleSet , err
141
+ }
142
+
143
+
144
+ func init () {
145
+ yrErrorVerbose = true
146
+ }
147
+
58
148
59
149
%}
60
150
225
315
// Forbid duplicate rules
226
316
for _ , r := range lexer.ruleSet.Rules {
227
317
if $3 == r.Identifier {
228
- return lexer.SetError (
318
+ return lexer.setError (
229
319
gyperror.DuplicateRuleError, `duplicate rule " %s" `, $3 )
230
320
}
231
321
}
@@ -329,7 +419,7 @@ tag_list
329
419
330
420
for _ , tag := range $1 {
331
421
if tag == $2 {
332
- return lexer.SetError (
422
+ return lexer.setError (
333
423
gyperror.DuplicateTagError, `duplicate tag " %s" `, $2 )
334
424
}
335
425
}
@@ -449,7 +539,7 @@ string_modifiers
449
539
| string_modifiers string_modifier
450
540
{
451
541
if $1.modifiers & $2.modifiers != 0 {
452
- return asLexer(yrlex).SetError (
542
+ return asLexer(yrlex).setError (
453
543
gyperror.DuplicateModifierError, `duplicate modifier`)
454
544
}
455
545
@@ -492,19 +582,19 @@ string_modifier
492
582
lexer := asLexer(yrlex)
493
583
494
584
if $3 < 0 {
495
- return lexer.SetError (
585
+ return lexer.setError (
496
586
gyperror.InvalidStringModifierError,
497
587
" lower bound for xor range exceeded (min: 0)" )
498
588
}
499
589
500
590
if $5 > 255 {
501
- return lexer.SetError (
591
+ return lexer.setError (
502
592
gyperror.InvalidStringModifierError,
503
593
" upper bound for xor range exceeded (max: 255)" )
504
594
}
505
595
506
596
if $3 > $5 {
507
- return lexer.SetError (
597
+ return lexer.setError (
508
598
gyperror.InvalidStringModifierError,
509
599
" xor lower bound exceeds upper bound" )
510
600
}
0 commit comments