parseRuleStatement is responsible for parsing a rule statement in the form: rule name(typ1 string, typ2 boolean) { EXPRESSION } This method assumes the current token points to the 'rule' token when it is called.
()
| 299 | // |
| 300 | // This method assumes the current token points to the 'rule' token when it is called. |
| 301 | func (p *Parser) parseRuleStatement() (*ast.RuleStatement, error) { |
| 302 | // Create a new RuleStatement |
| 303 | stmt := &ast.RuleStatement{Rule: p.currentToken} |
| 304 | |
| 305 | // Expect the next token to be an identifier (the name of the rule). |
| 306 | // If it's not an identifier, return an error. |
| 307 | if !p.expectAndNext(token.IDENT) { |
| 308 | return nil, p.Error() |
| 309 | } |
| 310 | stmt.Name = p.currentToken |
| 311 | |
| 312 | // Expect the next token to be a left parenthesis '(' starting the argument list. |
| 313 | if !p.expectAndNext(token.LP) { |
| 314 | return nil, p.Error() |
| 315 | } |
| 316 | |
| 317 | arguments := map[token.Token]ast.AttributeTypeStatement{} |
| 318 | args := map[string]string{} |
| 319 | |
| 320 | // Loop over the tokens until a right parenthesis ')' is encountered. |
| 321 | // In each iteration, two tokens are processed: an identifier (arg name) and its type. |
| 322 | for !p.peekTokenIs(token.RP) { |
| 323 | // Expect the first token to be the parameter's identifier. |
| 324 | if !p.expectAndNext(token.IDENT) { |
| 325 | return nil, p.Error() |
| 326 | } |
| 327 | argument := p.currentToken |
| 328 | arg := p.currentToken.Literal |
| 329 | |
| 330 | // Expect the second token to be the parameter's type. |
| 331 | if !p.expectAndNext(token.IDENT) { |
| 332 | return nil, p.Error() |
| 333 | } |
| 334 | |
| 335 | if p.peekTokenIs(token.LSB) { // Check if the next token is '[' |
| 336 | arguments[argument] = ast.AttributeTypeStatement{ |
| 337 | Type: p.currentToken, |
| 338 | IsArray: true, // Marking the type as an array |
| 339 | } |
| 340 | args[arg] = p.currentToken.Literal + "[]" // Store the argument type as string with "[]" suffix |
| 341 | p.next() // Move to the '[' token |
| 342 | if !p.expectAndNext(token.RSB) { // Expect and move to the ']' token |
| 343 | return nil, p.Error() |
| 344 | } |
| 345 | } else { |
| 346 | arguments[argument] = ast.AttributeTypeStatement{ |
| 347 | Type: p.currentToken, |
| 348 | IsArray: false, // Marking the type as not an array |
| 349 | } |
| 350 | args[arg] = p.currentToken.Literal // Store the regular argument type |
| 351 | } |
| 352 | |
| 353 | // If the next token is a comma, there are more parameters to parse. |
| 354 | // Continue to the next iteration. |
| 355 | if p.peekTokenIs(token.COMMA) { |
| 356 | p.next() |
| 357 | continue |
| 358 | } else if !p.peekTokenIs(token.RP) { |
no test coverage detected