Best Syzkaller code snippet using ast.skipWhitespace
parse.go
Source:parse.go
...75 }76}77func parseStyleRule(offset int, tokens []token.Token) (int, []token.Token, *ast.StyleRule, error) {78 rule := &ast.StyleRule{}79 offset, tokens, selectors, err := parseSelectorList(skipWhitespace(offset, tokens))80 if err != nil {81 return offset, tokens, nil, err82 }83 rule.Selectors = selectors84 offset, tokens = skipWhitespace(offset, tokens)85 switch peek(tokens, 1).(type) {86 case token.OpenCurly:87 offset, tokens = offset+1, tokens[1:]88 default:89 return offset, tokens, nil, SyntaxError{90 Offset: offset,91 Message: `unexpected token, expected "{"`,92 }93 }94 offset, tokens, declarations, err := parseDeclarationList(skipWhitespace(offset, tokens))95 if err != nil {96 return offset, tokens, rule, err97 }98 rule.Declarations = declarations99 offset, tokens = skipWhitespace(offset, tokens)100 switch peek(tokens, 1).(type) {101 case token.CloseCurly:102 return offset + 1, tokens[1:], rule, nil103 default:104 return offset, tokens, rule, SyntaxError{105 Offset: offset,106 Message: `unexpected token, expected "}"`,107 }108 }109}110func parseImportRule(offset int, tokens []token.Token) (int, []token.Token, *ast.ImportRule, error) {111 rule := &ast.ImportRule{}112 offset, tokens = skipWhitespace(offset, tokens)113 switch t := peek(tokens, 1).(type) {114 case token.Url:115 parsed, err := url.Parse(t.Value)116 if err != nil {117 return offset, tokens, nil, SyntaxError{118 Offset: offset,119 Message: err.Error(),120 }121 }122 rule.URL = parsed123 offset, tokens = offset+1, tokens[1:]124 case token.String:125 parsed, err := url.Parse(t.Value)126 if err != nil {127 return offset, tokens, nil, SyntaxError{128 Offset: offset,129 Message: err.Error(),130 }131 }132 rule.URL = parsed133 offset, tokens = offset+1, tokens[1:]134 case token.Function:135 if t.Value != "url" {136 return offset, tokens, nil, SyntaxError{137 Offset: offset,138 Message: `unexpected function, expected "url()"`,139 }140 }141 offset, tokens = skipWhitespace(offset+1, tokens[1:])142 switch t := peek(tokens, 1).(type) {143 case token.String:144 parsed, err := url.Parse(t.Value)145 if err != nil {146 return offset, tokens, nil, SyntaxError{147 Offset: offset,148 Message: err.Error(),149 }150 }151 rule.URL = parsed152 offset, tokens = offset+1, tokens[1:]153 default:154 return offset, tokens, nil, SyntaxError{155 Offset: offset,156 Message: "unexpected token, expected string",157 }158 }159 offset, tokens = skipWhitespace(offset, tokens)160 switch peek(tokens, 1).(type) {161 case token.CloseParen:162 offset, tokens = offset+1, tokens[1:]163 default:164 return offset, tokens, nil, SyntaxError{165 Offset: offset,166 Message: `unexpected token, expected ")"`,167 }168 }169 }170 offset, tokens = skipWhitespace(offset, tokens)171 switch peek(tokens, 1).(type) {172 case token.Semicolon:173 return offset + 1, tokens[1:], rule, nil174 case nil:175 return offset, tokens, rule, nil176 default:177 offset, tokens, conditions, err := parseMediaQueryList(offset, tokens)178 if err != nil {179 return offset, tokens, rule, err180 }181 rule.Conditions = conditions182 offset, tokens = skipWhitespace(offset, tokens)183 switch peek(tokens, 1).(type) {184 case token.Semicolon:185 return offset + 1, tokens[1:], rule, nil186 case nil:187 return offset, tokens, rule, nil188 default:189 return offset, tokens, nil, SyntaxError{190 Offset: offset,191 Message: `unexpected token, expected ";"`,192 }193 }194 }195}196func parseMediaRule(offset int, tokens []token.Token) (int, []token.Token, *ast.MediaRule, error) {197 rule := &ast.MediaRule{}198 offset, tokens, conditions, err := parseMediaQueryList(skipWhitespace(offset, tokens))199 if err != nil {200 return offset, tokens, nil, err201 }202 rule.Conditions = conditions203 offset, tokens = skipWhitespace(offset, tokens)204 switch peek(tokens, 1).(type) {205 case token.OpenCurly:206 offset, tokens = offset+1, tokens[1:]207 default:208 return offset, tokens, nil, SyntaxError{209 Offset: offset,210 Message: `unexpected token, expected "{"`,211 }212 }213 offset, tokens, styleSheet, err := parseStyleSheet(offset, tokens)214 if err != nil {215 return offset, tokens, nil, err216 }217 rule.StyleSheet = styleSheet218 offset, tokens = skipWhitespace(offset, tokens)219 switch peek(tokens, 1).(type) {220 case token.CloseCurly:221 return offset + 1, tokens[1:], rule, nil222 default:223 return offset, tokens, nil, SyntaxError{224 Offset: offset,225 Message: `unexpected token, expected "}"`,226 }227 }228}229func parseFontFaceRule(offset int, tokens []token.Token) (int, []token.Token, *ast.FontFaceRule, error) {230 rule := &ast.FontFaceRule{}231 offset, tokens = skipWhitespace(offset, tokens)232 switch peek(tokens, 1).(type) {233 case token.OpenCurly:234 offset, tokens = offset+1, tokens[1:]235 default:236 return offset, tokens, nil, SyntaxError{237 Offset: offset,238 Message: `unexpected token, expected "{"`,239 }240 }241 offset, tokens, declarations, err := parseDeclarationList(skipWhitespace(offset, tokens))242 if err != nil {243 return offset, tokens, rule, err244 }245 rule.Declarations = declarations246 offset, tokens = skipWhitespace(offset, tokens)247 switch peek(tokens, 1).(type) {248 case token.CloseCurly:249 return offset + 1, tokens[1:], rule, nil250 default:251 return offset, tokens, rule, SyntaxError{252 Offset: offset,253 Message: `unexpected token, expected "}"`,254 }255 }256}257func parseKeyframesRule(offset int, tokens []token.Token, prefix string) (int, []token.Token, *ast.KeyframesRule, error) {258 rule := &ast.KeyframesRule{Prefix: prefix}259 offset, tokens = skipWhitespace(offset, tokens)260 switch t := peek(tokens, 1).(type) {261 case token.Ident:262 rule.Name = t.Value263 case token.String:264 rule.Name = t.Value265 default:266 return offset, tokens, nil, SyntaxError{267 Offset: offset,268 Message: "unexpected token, expected string or ident",269 }270 }271 offset, tokens = skipWhitespace(offset+1, tokens[1:])272 switch peek(tokens, 1).(type) {273 case token.OpenCurly:274 offset, tokens = offset+1, tokens[1:]275 default:276 return offset, tokens, nil, SyntaxError{277 Offset: offset,278 Message: `unexpected token, expected "{"`,279 }280 }281 for {282 switch peek(tokens, 1).(type) {283 case token.Whitespace:284 offset, tokens = offset+1, tokens[1:]285 case token.CloseCurly:286 return offset + 1, tokens[1:], rule, nil287 default:288 var (289 block *ast.KeyframeBlock290 err error291 )292 offset, tokens, block, err = parseKeyframeBlock(offset, tokens)293 if err != nil {294 return offset, tokens, rule, err295 }296 rule.Blocks = append(rule.Blocks, block)297 }298 }299}300func parseKeyframeBlock(offset int, tokens []token.Token) (int, []token.Token, *ast.KeyframeBlock, error) {301 block := &ast.KeyframeBlock{}302 switch t := peek(tokens, 1).(type) {303 case token.Ident:304 switch t.Value {305 case "from":306 block.Selector = 0307 case "to":308 block.Selector = 1309 default:310 return offset, tokens, nil, SyntaxError{311 Offset: offset,312 Message: `unexpected token, expected "from" or "to"`,313 }314 }315 case token.Percentage:316 block.Selector = t.Value317 default:318 return offset, tokens, nil, SyntaxError{319 Offset: offset,320 Message: `unexpected token, expected "from", "to", or percentage`,321 }322 }323 offset, tokens = skipWhitespace(offset+1, tokens[1:])324 switch peek(tokens, 1).(type) {325 case token.OpenCurly:326 var (327 declarations []*ast.Declaration328 err error329 )330 offset, tokens, declarations, err = parseDeclarationList(skipWhitespace(offset+1, tokens[1:]))331 if err != nil {332 return offset, tokens, nil, err333 }334 block.Declarations = declarations335 default:336 return offset, tokens, nil, SyntaxError{337 Offset: offset,338 Message: `unexpected token, expected "{"`,339 }340 }341 offset, tokens = skipWhitespace(offset, tokens)342 switch peek(tokens, 1).(type) {343 case token.CloseCurly:344 return offset + 1, tokens[1:], block, nil345 default:346 return offset, tokens, nil, SyntaxError{347 Offset: offset,348 Message: `unexpected token, expected "}"`,349 }350 }351}352func parseSupportsRule(offset int, tokens []token.Token) (int, []token.Token, *ast.SupportsRule, error) {353 rule := &ast.SupportsRule{}354 offset, tokens, condition, err := parseSupportsCondition(skipWhitespace(offset, tokens))355 if err != nil {356 return offset, tokens, nil, err357 }358 rule.Condition = condition359 offset, tokens = skipWhitespace(offset, tokens)360 switch peek(tokens, 1).(type) {361 case token.OpenCurly:362 offset, tokens = offset+1, tokens[1:]363 default:364 return offset, tokens, nil, SyntaxError{365 Offset: offset,366 Message: `unexpected token, expected "{"`,367 }368 }369 offset, tokens, styleSheet, err := parseStyleSheet(skipWhitespace(offset, tokens))370 if err != nil {371 return offset, tokens, nil, err372 }373 rule.StyleSheet = styleSheet374 switch peek(tokens, 1).(type) {375 case token.CloseCurly:376 return offset + 1, tokens[1:], rule, nil377 default:378 return offset, tokens, nil, SyntaxError{379 Offset: offset,380 Message: `unexpected token, expected "}"`,381 }382 }383}384func parsePageRule(offset int, tokens []token.Token) (int, []token.Token, *ast.PageRule, error) {385 rule := &ast.PageRule{}386 offset, tokens, selectors, err := parsePageSelectorList(skipWhitespace(offset, tokens))387 if err != nil {388 return offset, tokens, nil, err389 }390 rule.Selectors = selectors391 offset, tokens = skipWhitespace(offset, tokens)392 switch peek(tokens, 1).(type) {393 case token.OpenCurly:394 offset, tokens = offset+1, tokens[1:]395 default:396 return offset, tokens, nil, SyntaxError{397 Offset: offset,398 Message: `unexpected token, expected "{"`,399 }400 }401 offset, tokens, components, err := parsePageComponentList(skipWhitespace(offset, tokens))402 if err != nil {403 return offset, tokens, nil, err404 }405 rule.Components = components406 offset, tokens = skipWhitespace(offset, tokens)407 switch peek(tokens, 1).(type) {408 case token.CloseCurly:409 return offset + 1, tokens[1:], rule, nil410 default:411 return offset, tokens, nil, SyntaxError{412 Offset: offset,413 Message: `unexpected token, expected "}"`,414 }415 }416}417func parseDeclarationList(offset int, tokens []token.Token) (int, []token.Token, []*ast.Declaration, error) {418 var declarations []*ast.Declaration419 for {420 switch peek(tokens, 1).(type) {421 case token.Whitespace, token.Semicolon:422 offset, tokens = offset+1, tokens[1:]423 case token.CloseCurly:424 return offset, tokens, declarations, nil425 default:426 var (427 declaration *ast.Declaration428 err error429 )430 offset, tokens, declaration, err = parseDeclaration(offset, tokens)431 if err != nil {432 return offset, tokens, nil, err433 }434 declarations = append(declarations, declaration)435 }436 }437}438func parseDeclaration(offset int, tokens []token.Token) (int, []token.Token, *ast.Declaration, error) {439 declaration := &ast.Declaration{}440 switch t := peek(tokens, 1).(type) {441 case token.Ident:442 declaration.Name = t.Value443 default:444 return offset, tokens, nil, SyntaxError{445 Offset: offset,446 Message: `unexpected token, expected ident`,447 }448 }449 offset, tokens = skipWhitespace(offset+1, tokens[1:])450 switch peek(tokens, 1).(type) {451 case token.Colon:452 offset, tokens = offset+1, tokens[1:]453 default:454 return offset, tokens, nil, SyntaxError{455 Offset: offset,456 Message: `unexpected token, expected ":"`,457 }458 }459 offset, tokens = skipWhitespace(offset, tokens)460 for {461 switch peek(tokens, 1).(type) {462 case token.CloseParen, token.CloseCurly, token.CloseSquare, token.Semicolon, nil:463 return offset, tokens, declaration, nil464 default:465 var (466 component []token.Token467 err error468 )469 offset, tokens, component, err = parseComponent(offset, tokens)470 if err != nil {471 return offset, tokens, nil, err472 }473 declaration.Value = append(declaration.Value, component...)474 }475 }476}477func parseComponent(offset int, tokens []token.Token) (int, []token.Token, []token.Token, error) {478 component := tokens[:1]479 switch peek(tokens, 1).(type) {480 case token.OpenParen, token.Function:481 offset, tokens, block, err := parseParenBlock(offset+1, tokens[1:])482 if err != nil {483 return offset, tokens, nil, err484 }485 return offset, tokens, append(component, block...), nil486 case nil:487 return offset, tokens, nil, nil488 default:489 return offset + 1, tokens[1:], component, nil490 }491}492func parseParenBlock(offset int, tokens []token.Token) (int, []token.Token, []token.Token, error) {493 var block []token.Token494 for {495 switch next := peek(tokens, 1).(type) {496 case token.CloseParen:497 return offset + 1, tokens[1:], append(block, next), nil498 case nil:499 return offset, tokens, block, SyntaxError{500 Offset: offset,501 Message: `unexpected token, expected ")"`,502 }503 default:504 var (505 component []token.Token506 err error507 )508 offset, tokens, component, err = parseComponent(offset, tokens)509 if err != nil {510 return offset, tokens, block, err511 }512 block = append(block, component...)513 }514 }515}516func parseSelectorList(offset int, tokens []token.Token) (int, []token.Token, []ast.Selector, error) {517 var selectors []ast.Selector518 for {519 switch peek(tokens, 1).(type) {520 case token.Whitespace, token.Comma:521 offset, tokens = offset+1, tokens[1:]522 case token.OpenCurly:523 return offset, tokens, selectors, nil524 default:525 var (526 selector ast.Selector527 err error528 )529 offset, tokens, selector, err = parseSelector(offset, tokens)530 if err != nil {531 return offset, tokens, selectors, err532 }533 selectors = append(selectors, selector)534 }535 }536}537func parseSelector(offset int, tokens []token.Token) (int, []token.Token, ast.Selector, error) {538 var (539 left ast.Selector540 right ast.Selector541 err error542 )543 for {544 switch t := peek(tokens, 1).(type) {545 case token.Delim:546 switch t.Value {547 case '.':548 offset, tokens, right, err = parseClassSelector(offset+1, tokens[1:])549 if err != nil {550 return offset, tokens, left, err551 }552 left = combineSelectors(left, right)553 case '#':554 offset, tokens, right, err = parseIDSelector(offset+1, tokens[1:])555 if err != nil {556 return offset, tokens, left, err557 }558 left = combineSelectors(left, right)559 case '*':560 offset, tokens, right = offset+1, tokens[1:], &ast.TypeSelector{Name: "*"}561 left = combineSelectors(left, right)562 case '>', '~', '+':563 offset, tokens, left, err = parseComplexSelector(offset, tokens, left)564 if err != nil {565 return offset, tokens, left, err566 }567 default:568 return offset, tokens, left, nil569 }570 case token.OpenSquare:571 offset, tokens, right, err = parseAttributeSelector(offset+1, tokens[1:])572 if err != nil {573 return offset, tokens, left, err574 }575 left = combineSelectors(left, right)576 case token.Ident:577 offset, tokens, right, err = parseTypeSelector(offset, tokens)578 if err != nil {579 return offset, tokens, left, err580 }581 left = combineSelectors(left, right)582 case token.Colon:583 offset, tokens, right, err = parsePseudoSelector(offset+1, tokens[1:])584 if err != nil {585 return offset, tokens, left, err586 }587 left = combineSelectors(left, right)588 case token.Whitespace:589 if len(tokens) > 1 && startsSelector(tokens[1]) {590 offset, tokens, left, err = parseComplexSelector(offset, tokens, left)591 if err != nil {592 return offset, tokens, left, err593 }594 } else {595 offset, tokens = offset+1, tokens[1:]596 }597 default:598 return offset, tokens, left, nil599 }600 }601}602func startsSelector(t token.Token) bool {603 switch t := t.(type) {604 case token.Ident, token.Colon:605 return true606 case token.Delim:607 return t.Value == '.' || t.Value == '#' || t.Value == '*'608 }609 return false610}611func combineSelectors(left ast.Selector, right ast.Selector) ast.Selector {612 if left == nil {613 return right614 }615 return &ast.CompoundSelector{Left: left, Right: right}616}617func parseIDSelector(offset int, tokens []token.Token) (int, []token.Token, *ast.IdSelector, error) {618 selector := &ast.IdSelector{}619 switch t := peek(tokens, 1).(type) {620 case token.Ident:621 selector.Name = t.Value622 return offset + 1, tokens[1:], selector, nil623 default:624 return offset, tokens, nil, SyntaxError{625 Offset: offset,626 Message: "unexpected token, expected id",627 }628 }629}630func parseClassSelector(offset int, tokens []token.Token) (int, []token.Token, *ast.ClassSelector, error) {631 selector := &ast.ClassSelector{}632 switch t := peek(tokens, 1).(type) {633 case token.Ident:634 selector.Name = t.Value635 return offset + 1, tokens[1:], selector, nil636 default:637 return offset, tokens, nil, SyntaxError{638 Offset: offset,639 Message: "unexpected token, expected class",640 }641 }642}643func parseAttributeSelector(offset int, tokens []token.Token) (int, []token.Token, *ast.AttributeSelector, error) {644 selector := &ast.AttributeSelector{}645 offset, tokens = skipWhitespace(offset, tokens)646 switch t := peek(tokens, 1).(type) {647 case token.Ident:648 selector.Name = t.Value649 offset, tokens = offset+1, tokens[1:]650 default:651 return offset, tokens, nil, SyntaxError{652 Offset: offset,653 Message: "unexpected token, expected attribute name",654 }655 }656 offset, tokens = skipWhitespace(offset, tokens)657 switch t := peek(tokens, 1).(type) {658 case token.CloseSquare:659 return offset + 1, tokens[1:], selector, nil660 case token.Delim:661 switch t.Value {662 case '=':663 selector.Matcher = "="664 offset, tokens = offset+1, tokens[1:]665 case '~', '|', '^', '$', '*':666 offset, tokens = offset+1, tokens[1:]667 switch u := peek(tokens, 1).(type) {668 case token.Delim:669 if u.Value == '=' {670 switch t.Value {671 case '~':672 selector.Matcher = "~="673 case '|':674 selector.Matcher = "|="675 case '^':676 selector.Matcher = "^="677 case '$':678 selector.Matcher = "$="679 case '*':680 selector.Matcher = "*="681 }682 offset, tokens = offset+1, tokens[1:]683 }684 }685 }686 }687 offset, tokens = skipWhitespace(offset, tokens)688 switch t := peek(tokens, 1).(type) {689 case token.String:690 selector.Value = fmt.Sprintf("%c%s%[1]c", t.Mark, t.Value)691 case token.Ident:692 selector.Value = t.Value693 default:694 return offset, tokens, nil, SyntaxError{695 Offset: offset,696 Message: "unexpected token, expected attribute value",697 }698 }699 offset, tokens = skipWhitespace(offset+1, tokens[1:])700 switch t := peek(tokens, 1).(type) {701 case token.Ident:702 switch t.Value {703 case "i", "s":704 selector.Modifier = t.Value705 offset, tokens = offset+1, tokens[1:]706 }707 }708 offset, tokens = skipWhitespace(offset, tokens)709 switch peek(tokens, 1).(type) {710 case token.CloseSquare:711 return offset + 1, tokens[1:], selector, nil712 default:713 return offset, tokens, nil, SyntaxError{714 Offset: offset,715 Message: `unexpected token, expected "]"`,716 }717 }718}719func parseTypeSelector(offset int, tokens []token.Token) (int, []token.Token, *ast.TypeSelector, error) {720 selector := &ast.TypeSelector{}721 switch t := peek(tokens, 1).(type) {722 case token.Ident:723 selector.Name = t.Value724 return offset + 1, tokens[1:], selector, nil725 default:726 return offset, tokens, nil, SyntaxError{727 Offset: offset,728 Message: "unexpected token, expected type",729 }730 }731}732func parsePseudoSelector(offset int, tokens []token.Token) (int, []token.Token, *ast.PseudoSelector, error) {733 selector := &ast.PseudoSelector{Name: ":"}734 switch peek(tokens, 1).(type) {735 case token.Colon:736 selector.Name += ":"737 offset, tokens = offset+1, tokens[1:]738 }739 switch t := peek(tokens, 1).(type) {740 case token.Ident:741 selector.Name += t.Value742 return offset + 1, tokens[1:], selector, nil743 case token.Function:744 selector.Name += t.Value745 offset, tokens = offset+1, tokens[1:]746 for {747 switch t := peek(tokens, 1).(type) {748 case token.CloseParen:749 return offset + 1, tokens[1:], selector, nil750 case nil:751 return offset, tokens, nil, SyntaxError{752 Offset: offset,753 Message: `unexpected token, expected ")"`,754 }755 default:756 selector.Value = append(selector.Value, t)757 offset, tokens = offset+1, tokens[1:]758 }759 }760 default:761 return offset, tokens, nil, SyntaxError{762 Offset: offset,763 Message: "unexpected token, expected ident",764 }765 }766}767func parseComplexSelector(offset int, tokens []token.Token, left ast.Selector) (int, []token.Token, *ast.ComplexSelector, error) {768 selector := &ast.ComplexSelector{Left: left}769 switch t := peek(tokens, 1).(type) {770 case token.Whitespace:771 selector.Combinator = ' '772 case token.Delim:773 switch t.Value {774 case '>', '~', '+':775 selector.Combinator = t.Value776 default:777 return offset, tokens, nil, SyntaxError{778 Offset: offset,779 Message: "unexpected token, expected selector combinator",780 }781 }782 default:783 return offset, tokens, nil, SyntaxError{784 Offset: offset,785 Message: "unexpected token, expected selector combinator",786 }787 }788 var (789 right ast.Selector790 err error791 )792 offset, tokens, right, err = parseSelector(skipWhitespace(offset+1, tokens[1:]))793 if err != nil {794 return offset, tokens, nil, err795 }796 selector.Right = right797 return offset, tokens, selector, nil798}799func parseMediaQueryList(offset int, tokens []token.Token) (int, []token.Token, []*ast.MediaQuery, error) {800 var mediaQueries []*ast.MediaQuery801 for {802 offset, tokens = skipWhitespace(offset, tokens)803 var (804 mediaQuery *ast.MediaQuery805 err error806 )807 offset, tokens, mediaQuery, err = parseMediaQuery(offset, tokens)808 if err != nil {809 return offset, tokens, nil, err810 }811 mediaQueries = append(mediaQueries, mediaQuery)812 offset, tokens = skipWhitespace(offset, tokens)813 switch peek(tokens, 1).(type) {814 case token.Comma:815 offset, tokens = offset+1, tokens[1:]816 case token.OpenCurly, token.Semicolon, nil:817 return offset, tokens, mediaQueries, nil818 default:819 return offset, tokens, mediaQueries, SyntaxError{820 Offset: offset,821 Message: "unexpected token",822 }823 }824 }825}826func parseMediaQuery(offset int, tokens []token.Token) (int, []token.Token, *ast.MediaQuery, error) {827 mediaQuery := &ast.MediaQuery{}828 switch t := peek(tokens, 1).(type) {829 case token.Ident:830 switch t.Value {831 case "not", "only":832 mediaQuery.Qualifier = t.Value833 offset, tokens = offset+1, tokens[1:]834 }835 case token.OpenParen:836 var (837 condition ast.MediaCondition838 err error839 )840 offset, tokens, condition, err = parseMediaCondition(offset, tokens)841 if err != nil {842 return offset, tokens, nil, err843 }844 mediaQuery.Condition = condition845 return offset, tokens, mediaQuery, nil846 }847 offset, tokens = skipWhitespace(offset, tokens)848 switch t := peek(tokens, 1).(type) {849 case token.Ident:850 switch t.Value {851 case "not":852 case "only":853 case "and":854 case "or":855 return offset, tokens, nil, SyntaxError{856 Offset: offset,857 Message: "unexpected token, expected media type",858 }859 default:860 mediaQuery.Type = t.Value861 offset, tokens = offset+1, tokens[1:]862 }863 default:864 return offset, tokens, nil, SyntaxError{865 Offset: offset,866 Message: "unexpected token",867 }868 }869 return offset, tokens, mediaQuery, nil870}871func parseMediaCondition(offset int, tokens []token.Token) (int, []token.Token, ast.MediaCondition, error) {872 switch t := peek(tokens, 1).(type) {873 case token.Ident:874 if t.Value == "not" {875 var (876 condition ast.MediaCondition877 err error878 )879 offset, tokens, condition, err = parseMediaExpression(880 skipWhitespace(offset+1, tokens[1:]),881 )882 if err != nil {883 return offset, tokens, nil, err884 }885 condition = &ast.MediaNegation{Condition: condition}886 return offset, tokens, condition, nil887 }888 return offset, tokens, nil, SyntaxError{889 Offset: offset,890 Message: "unexpected token",891 }892 default:893 var (894 left ast.MediaCondition895 err error896 )897 offset, tokens, left, err = parseMediaExpression(offset, tokens)898 if err != nil {899 return offset, tokens, nil, err900 }901 var operator string902 for {903 offset, tokens = skipWhitespace(offset, tokens)904 switch t := peek(tokens, 1).(type) {905 case token.Ident:906 switch t.Value {907 case "and", "or":908 if operator == "" || operator == t.Value {909 operator = t.Value910 } else {911 return offset, tokens, nil, SyntaxError{912 Offset: offset,913 Message: `unexpected token, expected "` + operator + `"`,914 }915 }916 offset, tokens = offset+1, tokens[1:]917 default:918 return offset, tokens, nil, SyntaxError{919 Offset: offset,920 Message: `unexpected token, expected "and" or "or"`,921 }922 }923 offset, tokens = skipWhitespace(offset, tokens)924 var right ast.MediaCondition925 offset, tokens, right, err = parseMediaExpression(offset, tokens)926 if err != nil {927 return offset, tokens, nil, err928 }929 left = &ast.MediaOperation{930 Operator: operator,931 Left: left,932 Right: right,933 }934 default:935 return offset, tokens, left, nil936 }937 }938 }939}940func parseMediaExpression(offset int, tokens []token.Token) (int, []token.Token, ast.MediaCondition, error) {941 if offset, tokens, feature, err := parseMediaFeature(offset, tokens); err == nil {942 return offset, tokens, feature, nil943 }944 switch peek(tokens, 1).(type) {945 case token.OpenParen:946 offset, tokens = offset+1, tokens[1:]947 default:948 return offset, tokens, nil, SyntaxError{949 Offset: offset,950 Message: `unexpected token, expected "("`,951 }952 }953 offset, tokens = skipWhitespace(offset, tokens)954 var (955 condition ast.MediaCondition956 err error957 )958 offset, tokens, condition, err = parseMediaCondition(offset, tokens)959 if err != nil {960 return offset, tokens, condition, err961 }962 offset, tokens = skipWhitespace(offset, tokens)963 switch peek(tokens, 1).(type) {964 case token.CloseParen:965 return offset + 1, tokens[1:], condition, nil966 default:967 return offset, tokens, nil, SyntaxError{968 Offset: offset,969 Message: `unexpected token, expected ")"`,970 }971 }972}973func parseMediaFeature(offset int, tokens []token.Token) (int, []token.Token, *ast.MediaFeature, error) {974 feature := &ast.MediaFeature{}975 switch peek(tokens, 1).(type) {976 case token.OpenParen:977 offset, tokens = offset+1, tokens[1:]978 default:979 return offset, tokens, nil, SyntaxError{980 Offset: offset,981 Message: `unexpected token, expected "("`,982 }983 }984 offset, tokens = skipWhitespace(offset, tokens)985 switch t := peek(tokens, 1).(type) {986 case token.Ident:987 feature.Name = t.Value988 offset, tokens = offset+1, tokens[1:]989 default:990 return offset, tokens, nil, SyntaxError{991 Offset: offset,992 Message: "unexpected token, expected ident",993 }994 }995 offset, tokens = skipWhitespace(offset, tokens)996 switch peek(tokens, 1).(type) {997 case token.Colon:998 offset, tokens = offset+1, tokens[1:]999 default:1000 return offset, tokens, nil, SyntaxError{1001 Offset: offset,1002 Message: `unexpected token, expected ":"`,1003 }1004 }1005 offset, tokens = skipWhitespace(offset, tokens)1006 switch t := peek(tokens, 1).(type) {1007 case token.Number:1008 feature.Value = &ast.MediaValuePlain{Value: t}1009 case token.Dimension:1010 feature.Value = &ast.MediaValuePlain{Value: t}1011 case token.Ident:1012 feature.Value = &ast.MediaValuePlain{Value: t}1013 default:1014 return offset, tokens, nil, SyntaxError{1015 Offset: offset,1016 Message: `unexpected token, expected number, dimension, or ident`,1017 }1018 }1019 offset, tokens = skipWhitespace(offset+1, tokens[1:])1020 switch peek(tokens, 1).(type) {1021 case token.CloseParen:1022 offset, tokens = offset+1, tokens[1:]1023 default:1024 return offset, tokens, nil, SyntaxError{1025 Offset: offset,1026 Message: `unexpected token, expected ")"`,1027 }1028 }1029 return offset, tokens, feature, nil1030}1031func parseSupportsCondition(offset int, tokens []token.Token) (int, []token.Token, ast.SupportsCondition, error) {1032 switch t := peek(tokens, 1).(type) {1033 case token.Ident:1034 if t.Value == "not" {1035 var (1036 condition ast.SupportsCondition1037 err error1038 )1039 offset, tokens, condition, err = parseSupportsExpression(1040 skipWhitespace(offset+1, tokens[1:]),1041 )1042 if err != nil {1043 return offset, tokens, nil, err1044 }1045 condition = &ast.SupportsNegation{Condition: condition}1046 return offset, tokens, condition, nil1047 }1048 return offset, tokens, nil, SyntaxError{1049 Offset: offset,1050 Message: "unexpected token",1051 }1052 default:1053 var (1054 left ast.SupportsCondition1055 err error1056 )1057 offset, tokens, left, err = parseSupportsExpression(offset, tokens)1058 if err != nil {1059 return offset, tokens, left, err1060 }1061 var operator string1062 for {1063 offset, tokens = skipWhitespace(offset, tokens)1064 switch t := peek(tokens, 1).(type) {1065 case token.Ident:1066 switch t.Value {1067 case "and", "or":1068 if operator == "" || operator == t.Value {1069 operator = t.Value1070 } else {1071 return offset, tokens, nil, SyntaxError{1072 Offset: offset,1073 Message: `unexpected token, expected "` + operator + `"`,1074 }1075 }1076 offset, tokens = offset+1, tokens[1:]1077 default:1078 return offset, tokens, nil, SyntaxError{1079 Offset: offset,1080 Message: `unexpected token, expected "and" or "or"`,1081 }1082 }1083 offset, tokens = skipWhitespace(offset, tokens)1084 var right ast.SupportsCondition1085 offset, tokens, right, err = parseSupportsExpression(offset, tokens)1086 if err != nil {1087 return offset, tokens, nil, err1088 }1089 left = &ast.SupportsOperation{1090 Operator: operator,1091 Left: left,1092 Right: right,1093 }1094 default:1095 return offset, tokens, left, nil1096 }1097 }1098 }1099}1100func parseSupportsExpression(offset int, tokens []token.Token) (int, []token.Token, ast.SupportsCondition, error) {1101 if offset, tokens, feature, err := parseSupportsFeature(offset, tokens); err == nil {1102 return offset, tokens, feature, nil1103 }1104 switch peek(tokens, 1).(type) {1105 case token.OpenParen:1106 offset, tokens = offset+1, tokens[1:]1107 default:1108 return offset, tokens, nil, SyntaxError{1109 Offset: offset,1110 Message: `unexpected token, expected "("`,1111 }1112 }1113 var (1114 condition ast.SupportsCondition1115 err error1116 )1117 offset, tokens, condition, err = parseSupportsCondition(offset, tokens)1118 if err != nil {1119 return offset, tokens, condition, err1120 }1121 offset, tokens = skipWhitespace(offset, tokens)1122 switch peek(tokens, 1).(type) {1123 case token.CloseParen:1124 return offset + 1, tokens[1:], condition, nil1125 default:1126 return offset, tokens, nil, SyntaxError{1127 Offset: offset,1128 Message: `unexpected token, expected ")"`,1129 }1130 }1131}1132func parseSupportsFeature(offset int, tokens []token.Token) (int, []token.Token, *ast.SupportsFeature, error) {1133 feature := &ast.SupportsFeature{}1134 switch peek(tokens, 1).(type) {1135 case token.OpenParen:1136 offset, tokens = offset+1, tokens[1:]1137 default:1138 return offset, tokens, nil, SyntaxError{1139 Offset: offset,1140 Message: `unexpected token, expected "("`,1141 }1142 }1143 offset, tokens = skipWhitespace(offset, tokens)1144 var (1145 declaration *ast.Declaration1146 err error1147 )1148 offset, tokens, declaration, err = parseDeclaration(offset, tokens)1149 if err != nil {1150 return offset, tokens, nil, err1151 }1152 feature.Declaration = declaration1153 offset, tokens = skipWhitespace(offset, tokens)1154 switch peek(tokens, 1).(type) {1155 case token.CloseParen:1156 offset, tokens = offset+1, tokens[1:]1157 default:1158 return offset, tokens, nil, SyntaxError{1159 Offset: offset,1160 Message: `unexpected token, expected ")"`,1161 }1162 }1163 return offset, tokens, feature, nil1164}1165func parsePageSelectorList(offset int, tokens []token.Token) (int, []token.Token, []*ast.PageSelector, error) {1166 var selectors []*ast.PageSelector1167 for {1168 switch peek(tokens, 1).(type) {1169 case token.Whitespace, token.Comma:1170 offset, tokens = offset+1, tokens[1:]1171 case token.OpenCurly:1172 return offset, tokens, selectors, nil1173 default:1174 var (1175 selector *ast.PageSelector1176 err error1177 )1178 offset, tokens, selector, err = parsePageSelector(offset, tokens)1179 if err != nil {1180 return offset, tokens, nil, err1181 }1182 selectors = append(selectors, selector)1183 }1184 }1185}1186func parsePageSelector(offset int, tokens []token.Token) (int, []token.Token, *ast.PageSelector, error) {1187 selector := &ast.PageSelector{}1188 switch t := peek(tokens, 1).(type) {1189 case token.Ident:1190 selector.Type = t.Value1191 offset, tokens = offset+1, tokens[1:]1192 }1193 for {1194 switch peek(tokens, 1).(type) {1195 case token.Colon:1196 switch t := peek(tokens, 2).(type) {1197 case token.Ident:1198 switch t.Value {1199 case "left", "right", "first", "blank":1200 selector.Classes = append(selector.Classes, ":"+t.Value)1201 offset, tokens = offset+2, tokens[2:]1202 default:1203 return offset, tokens, nil, SyntaxError{1204 Offset: offset,1205 Message: `unexpected token, expected page selector`,1206 }1207 }1208 default:1209 return offset, tokens, nil, SyntaxError{1210 Offset: offset,1211 Message: `unexpected token, expected page selector`,1212 }1213 }1214 default:1215 return offset, tokens, selector, nil1216 }1217 }1218}1219func parsePageComponentList(offset int, tokens []token.Token) (int, []token.Token, []ast.PageComponent, error) {1220 var pageComponents []ast.PageComponent1221 for {1222 switch peek(tokens, 1).(type) {1223 case token.Whitespace, token.Semicolon:1224 offset, tokens = offset+1, tokens[1:]1225 case token.CloseCurly:1226 return offset, tokens, pageComponents, nil1227 default:1228 var (1229 pageComponent ast.PageComponent1230 err error1231 )1232 offset, tokens, pageComponent, err = parsePageComponent(offset, tokens)1233 if err != nil {1234 return offset, tokens, nil, err1235 }1236 pageComponents = append(pageComponents, pageComponent)1237 }1238 }1239}1240func parsePageComponent(offset int, tokens []token.Token) (int, []token.Token, ast.PageComponent, error) {1241 switch peek(tokens, 1).(type) {1242 case token.Ident:1243 var (1244 declaration *ast.Declaration1245 err error1246 )1247 offset, tokens, declaration, err = parseDeclaration(offset, tokens)1248 if err != nil {1249 return offset, tokens, nil, err1250 }1251 return offset, tokens, &ast.PageDeclaration{Declaration: declaration}, nil1252 default:1253 return offset, tokens, nil, SyntaxError{1254 Offset: offset,1255 Message: `unexpected token, expected ident`,1256 }1257 }1258}1259func peek(tokens []token.Token, n int) token.Token {1260 if len(tokens) < n {1261 return nil1262 }1263 return tokens[n-1]1264}1265func skipWhitespace(offset int, tokens []token.Token) (int, []token.Token) {1266 if _, ok := peek(tokens, 1).(token.Whitespace); ok {1267 return offset + 1, tokens[1:]1268 }1269 return offset, tokens1270}...
parser.go
Source:parser.go
...35 var node ast.Stmt36 if p.tok == token.MACRO {37 from := p.pos38 p.next()39 p.skipWhitespace()40 if TokenIn(p.tok, token.IF, token.IFDEF, token.IFNDEF) {41 node = p.parseMacroLogicStmt(from)42 } else {43 node = p.parseMacroStmt(from)44 }45 } else {46 node = p.parseTextStmt()47 }48 if node != nil {49 block.Add(node)50 }51 }52 return block53}54// è·åå½åçå®å55func (p *Parser) curMacroIs(tok ...token.Token) bool {56 pp := p.clone()57 defer p.reset(pp)58 p.next() // #59 p.skipWhitespace()60 return TokenIn(p.tok, tok...)61}62// 解æä½63func (p *Parser) parseBodyStmts() ast.Stmt {64 block := &ast.BlockStmt{}65 for p.tok != token.EOF {66 var node ast.Stmt67 if p.tok == token.MACRO {68 if p.curMacroIs(p.tok, token.EOF, token.ELSE, token.ELSEIF, token.ENDIF) {69 break70 }71 from := p.pos72 p.next()73 p.skipWhitespace()74 if TokenIn(p.tok, token.IF, token.IFDEF, token.IFNDEF) {75 node = p.parseMacroLogicStmt(from)76 } else {77 node = p.parseMacroStmt(from)78 }79 } else {80 node = p.parseTextStmt()81 }82 if node != nil {83 block.Add(node)84 }85 }86 return block87}88// 解æå®è¯å¥89func (p *Parser) parseMacroStmt(from token.Pos) (node ast.Stmt) {90 switch p.tok {91 case token.INCLUDE:92 node = p.parseInclude(from)93 case token.ERROR, token.PRAGMA, token.WARNING:94 node = p.parseCmd(from)95 case token.LINE, token.INT:96 node = p.parseLine(from)97 case token.DEFINE:98 node = p.parseDefine(from)99 case token.UNDEF:100 node = p.parseUnDefine(from)101 default:102 node = p.parseInvalidStmt(from)103 }104 return105}106// 解æå®è¯å¥å½ä»¤107func (p *Parser) parseMacroLogicStmt(from token.Pos) (node ast.CondStmt) {108 _, tok, _ := p.next()109 var cond ast.CondStmt110 if tok == token.IF {111 cond = &ast.IfStmt{112 X: p.parseIfExpr(),113 }114 p.scanToMacroEnd(true)115 } else {116 p.next()117 p.skipWhitespace()118 off, _, name := p.expectedIdent()119 id := &ast.Ident{120 Offset: off,121 Name: name,122 }123 if tok == token.IFDEF {124 cond = &ast.IfDefStmt{125 Name: id,126 }127 } else {128 cond = &ast.IfNoDefStmt{129 Name: id,130 }131 }132 p.scanToMacroEnd(true)133 }134 node = cond135 cond.SetTrueStmt(p.parseBodyStmts())136 for p.tok == token.MACRO && p.curMacroIs(token.ELSEIF) {137 off := p.pos138 p.next() // #139 p.skipWhitespace()140 p.next() // elseif141 eif := &ast.ElseIfStmt{142 X: p.parseIfExpr(),143 }144 tt := p.parseBodyStmts()145 eif.SetTrueStmt(tt)146 eif.SetFromTO(off, p.pos)147 cond.SetFalseStmt(eif)148 cond = eif149 }150 if p.tok == token.MACRO && p.curMacroIs(token.ELSE) {151 p.next() // #152 p.skipWhitespace()153 p.next() // else154 p.scanToMacroEnd(true)155 cond.SetFalseStmt(p.parseBodyStmts())156 }157 if p.tok == token.MACRO && p.curMacroIs(token.ENDIF) {158 p.next() // #159 p.skipWhitespace()160 p.next() // endif161 p.scanToMacroEnd(true)162 } else {163 p.errorf(p.pos, "expected #endif")164 }165 node.SetFromTO(from, p.pos)166 return167}168// æå表达å¼169func (p *Parser) parseIfExpr() ast.MacroLiter {170 node := &ast.MacroLitArray{}171 for !isMacroEnd(p.tok) {172 // 解æ173 if isIdent(p.tok) {174 node.Append(p.parseIdentExpr())175 } else if TokenIn(p.tok, token.DEFINED) {176 node.Append(p.parseDefined())177 } else {178 node.Append(p.parseText())179 }180 }181 return nilIfEmpty(node)182}183// 解æ defined184func (p *Parser) parseDefined() (node ast.MacroLiter) {185 from := p.pos186 p.next() // defined187 id := &ast.Text{188 Offset: p.pos,189 Kind: token.DEFINED,190 Text: p.lit,191 }192 if v := p.parseDefinedValue(); v != nil {193 return &ast.UnaryExpr{194 Offset: from,195 Op: token.DEFINED,196 X: v,197 }198 }199 return id200}201func (p *Parser) parseDefinedValue() (node ast.MacroLiter) {202 pp := p.clone()203 if p.tryParenPair(true) {204 p.skipWhitespace()205 lp, _, _ := p.expected(token.LPAREN)206 v := p.parseDefinedValue()207 rp, _, _ := p.expected(token.RPAREN)208 return &ast.ParenExpr{209 Lparen: lp,210 X: v,211 Rparen: rp,212 }213 } else if p.nextNotEmptyIsIdent() {214 p.skipWhitespace()215 pos, _, lit := p.expectedIdent()216 return &ast.Ident{217 Offset: pos,218 Name: lit,219 }220 } else {221 defer p.reset(pp)222 p.errorf(p.pos, "unexpected token %v after defined", p.tok)223 return nil224 }225}226// #include <path>227// #include "path"228func (p *Parser) parseInclude(from token.Pos) ast.Stmt {229 p.next()230 p.skipWhitespace()231 pos, tok, lit := p.next()232 var path string233 typ := ast.IncludeOuter234 if tok == token.STRING {235 path = lit236 } else if tok == token.LSS {237 path = lit238 typ = ast.IncludeInner239 for {240 if tok == token.GTR || tok == token.NEWLINE || tok == token.EOF {241 if tok == token.NEWLINE {242 p.next()243 }244 break245 }246 pos, tok, lit = p.next()247 path += lit248 }249 } else {250 p.errorf(pos, "unexpected token %v", tok)251 }252 p.scanToMacroEnd(true)253 return &ast.IncludeStmt{254 From: from,255 To: pos,256 Path: path,257 Type: typ,258 }259}260// #error message261func (p *Parser) parseCmd(from token.Pos) ast.Stmt {262 node := &ast.MacroCmdStmt{263 Offset: from,264 Cmd: p.lit,265 Kind: p.tok,266 }267 to := p.scanToMacroEnd(false)268 node.Cmd = clearBackslash(p.scanner.Lit(from, to))269 return node270}271// #line number272// #line number "file"273// # number "file"274// # number275func (p *Parser) parseLine(from token.Pos) ast.Stmt {276 node := &ast.LineStmt{From: from}277 if p.tok == token.INT {278 node.Line = p.lit279 node.To = p.pos + token.Pos(len(p.lit))280 p.next()281 } else {282 p.next()283 p.skipWhitespace()284 node.To, _, node.Line = p.expected(token.INT)285 node.To = node.To + token.Pos(len(node.Line))286 }287 p.skipWhitespace()288 if p.tok == token.STRING {289 node.Path = p.lit290 node.To = p.pos + token.Pos(len(p.lit))291 p.next()292 }293 p.scanToMacroEnd(true)294 return node295}296// # any NEWLINE297func (p *Parser) parseInvalidStmt(from token.Pos) ast.Stmt {298 node := &ast.InvalidStmt{Offset: p.pos}299 p.errorf(p.pos, "invalid preprocessing directive #%s", p.lit)300 p.next()301 to := p.scanToMacroEnd(false)302 node.Text = p.scanner.Lit(from, to)303 return node304}305// #undef ident306func (p *Parser) parseUnDefine(from token.Pos) ast.Stmt {307 p.next()308 p.skipWhitespace()309 pos, _, name := p.expectedIdent()310 id := &ast.Ident{311 Offset: pos,312 Name: name,313 }314 end := p.pos315 p.scanToMacroEnd(true)316 return &ast.UnDefineStmt{317 From: from,318 To: end,319 Name: id,320 }321}322// define_statement =323// ( macro_prefix "#define" define_literal code_line ) .324func (p *Parser) parseDefine(from token.Pos) ast.Stmt {325 p.next()326 p.skipWhitespace()327 pos, _, name := p.expectedIdent()328 id := &ast.Ident{329 Offset: pos,330 Name: name,331 }332 if p.tok == token.LPAREN {333 node := &ast.FuncDefineStmt{From: from, Name: id}334 lp, _, _ := p.expected(token.LPAREN)335 list, err := p.parseIdentList()336 if err != nil {337 return &ast.BadExpr{338 Offset: from,339 Token: token.DEFINE,340 Lit: p.scanner.Lit(from, p.pos),341 }342 }343 rp, _, _ := p.expected(token.RPAREN)344 node.IdentList = list345 node.Lparen = lp346 node.Rparen = rp347 p.skipWhitespace()348 node.Body = p.parseMacroFuncBody()349 node.To = p.pos350 p.scanToMacroEnd(true)351 return node352 } else {353 node := &ast.ValDefineStmt{From: from, Name: id}354 p.skipWhitespace()355 node.Body = p.parseMacroTextBody()356 node.To = p.pos357 p.scanToMacroEnd(true)358 return node359 }360}361// 解æåæ°å表362func (p *Parser) parseIdentList() (params []*ast.Ident, err error) {363 params = []*ast.Ident{}364 p.skipWhitespace()365 for TokenNotIn(p.tok, token.RPAREN, token.NEWLINE, token.EOF) {366 if !isIdent(p.tok) {367 goto errExit368 } else {369 params = append(params, &ast.Ident{370 Offset: p.pos,371 Name: p.lit,372 })373 p.next() // ident374 p.skipWhitespace()375 if TokenIn(p.tok, token.RPAREN) {376 return377 }378 if p.tok != token.COMMA {379 goto errExit380 }381 p.next() // ,382 p.skipWhitespace()383 }384 }385 return386errExit:387 msg := fmt.Sprintf("%v may not appear in macro parameter list", p.tok)388 p.error(p.pos, msg)389 err = errors.New(msg)390 p.scanToMacroEnd(false)391 return392}393// 解æå®å½æ°å®ä¹ä½394// macro_body =395// < text_line / macro_literal > .396func (p *Parser) parseMacroFuncBody() (node *ast.MacroLitArray) {397 node = &ast.MacroLitArray{}398 for !isMacroEnd(p.tok) {399 // 解æ400 if TokenIn(p.tok, token.IDENT, token.FLOAT, token.INT, token.SHARP) || isIdent(p.tok) {401 node.Append(p.parseMacroExpr())402 } else if TokenIn(p.tok, token.DOUBLE_SHARP) {403 p.errorf(p.pos, "unexpected token %s in macro body", token.DOUBLE_SHARP)404 p.next()405 } else {406 node.Append(p.parseText())407 }408 }409 return nilIfEmpty(node)410}411// 解æå®å®ä¹ä½412func (p *Parser) parseMacroTextBody() (node *ast.MacroLitArray) {413 node = &ast.MacroLitArray{}414 for !isMacroEnd(p.tok) {415 // 解æ416 if isIdent(p.tok) {417 node.Append(p.parseMacroExpr())418 } else {419 node.Append(p.parseText())420 }421 }422 return nilIfEmpty(node)423}424// 解æææ¬è¯å¥425func (p *Parser) parseTextStmt() (node *ast.MacroLitArray) {426 node = &ast.MacroLitArray{}427 for TokenNotIn(p.tok, token.EOF, token.MACRO) {428 // 解æ429 if isIdent(p.tok) {430 node.Append(p.parseMacroLitExpr(false))431 } else {432 node.Append(p.parseText())433 }434 }435 return nilIfEmpty(node)436}437// 解æå®è¡¨è¾¾å¼438// å®å½æ°ä½å
439func (p *Parser) parseMacroExpr() (node ast.MacroLiter) {440 pos, tok, name := p.pos, p.tok, p.lit441 if TokenIn(p.tok, token.FLOAT, token.INT) {442 lit := &ast.LitExpr{443 Offset: pos,444 Kind: tok,445 Value: name,446 }447 p.next()448 return lit449 } else if isIdent(p.tok) {450 id := &ast.Ident{451 Offset: p.pos,452 Name: p.lit,453 }454 p.next()455 if p.nextNotEmptyIs(token.DOUBLE_SHARP) {456 p.skipWhitespace()457 sp, _, _ := p.next() //##458 p.skipWhitespace()459 pos, _, name := p.expectedIdent()460 return &ast.BinaryExpr{461 X: id,462 Offset: sp,463 Op: token.DOUBLE_SHARP,464 Y: &ast.Ident{465 Offset: pos,466 Name: name,467 },468 }469 }470 if p.tryParenPair(true) {471 return p.parseMacroCallExpr(id, true)472 }473 return id474 }475 return p.parseMacroSharpExpr()476}477// 表达å¼ä¸å
è¿ç®478func (p *Parser) parseMacroSharpExpr() (node ast.MacroLiter) {479 from := p.pos480 p.next() // #481 off, _, name := p.expectedIdent()482 x := &ast.Ident{483 Offset: off,484 Name: name,485 }486 return &ast.UnaryExpr{487 Offset: from,488 Op: token.SHARP,489 X: x,490 }491}492// 解ææ è¯ç¬¦åé¢é493// macro_liter =494// identifier495// / identifier ( "(" [ macro_argument ] ")" ) .496func (p *Parser) parseIdentExpr() (node ast.MacroLiter) {497 return p.parseMacroLitExpr(true)498}499// 解ææ è¯ç¬¦åé¢é500// macro_liter =501// identifier502// / identifier ( "(" [ macro_argument ] ")" ) .503func (p *Parser) parseMacroLitExpr(inMacro bool) (node ast.MacroLiter) {504 id := &ast.Ident{505 Offset: p.pos,506 Name: p.lit,507 }508 p.next()509 if p.tryParenPair(inMacro) {510 return p.parseMacroCallExpr(id, inMacro)511 }512 return id513}514func (p *Parser) parseMacroCallExpr(id *ast.Ident, inMacro bool) (node ast.MacroLiter) {515 p.skipWhitespace()516 lp, _, _ := p.expected(token.LPAREN)517 list := p.parseMacroArgument(inMacro)518 rp, _, _ := p.expected(token.RPAREN)519 return &ast.MacroCallExpr{520 From: id.Pos(),521 To: p.pos,522 Lparen: lp,523 Name: id,524 Rparen: rp,525 ParamList: list,526 }527}528// æ¥æ¾å®æ´ç()529func (p *Parser) tryParenPair(inMacro bool) bool {530 pp := p.clone()531 defer p.reset(pp)532 p.skipWhitespace()533 if p.tok == token.LPAREN {534 dp := 1535 p.next()536 for !isMacroArgEnd(inMacro, p.tok) {537 if p.tok == token.LPAREN {538 dp++539 }540 if p.tok == token.RPAREN {541 dp--542 if dp <= 0 {543 return true544 }545 }546 p.next()547 }548 }549 return false550}551// æ¾å°è°ç¨åæ°552// macro_argument =553// ( macro_param_lit < "," macro_param_lit > )554// / "(" text until ")" .555func (p *Parser) parseMacroArgument(inMacro bool) (node *ast.MacroLitArray) {556 node = &ast.MacroLitArray{}557 for TokenNotIn(p.tok, token.RPAREN) && !isMacroArgEnd(inMacro, p.tok) {558 node.Append(p.parseMacroArgumentLit(inMacro))559 if p.tok == token.COMMA {560 p.next() // ,561 }562 }563 return nilIfEmpty(node)564}565// åæ°åé¢é566// macro_param_lit =567// < macro_item > .568func (p *Parser) parseMacroArgumentLit(inMacro bool) (node ast.MacroLiter) {569 list := &ast.MacroLitArray{}570 for TokenNotIn(p.tok, token.COMMA, token.RPAREN) && !isMacroArgEnd(inMacro, p.tok) {571 if p.tok == token.LPAREN {572 list.Append(p.parseMacroArgumentParenItem(inMacro))573 } else {574 list.Append(p.parseMacroArgumentLitItem(inMacro))575 }576 }577 if len(*list) == 1 {578 return (*list)[0]579 }580 return nilIfEmpty(list)581}582// è·å ()583func (p *Parser) parseMacroArgumentParenItem(inMacro bool) (node ast.MacroLiter) {584 lp, _, _ := p.expected(token.LPAREN)585 list := p.parseMacroArgument(inMacro)586 rp, _, _ := p.expected(token.RPAREN)587 return &ast.ParenExpr{588 Lparen: lp,589 X: list,590 Rparen: rp,591 }592}593// macro_item =594// identifier595// / macro_call_expr596// / "text not , " .597func (p *Parser) parseMacroArgumentLitItem(inMacro bool) (node ast.MacroLiter) {598 if isIdent(p.tok) {599 return p.parseMacroLitExpr(inMacro)600 }601 return p.parseText()602}603// æ¯å¦æ¯åæ°ç»å°¾604func isMacroArgEnd(inMacro bool, tok token.Token) bool {605 if inMacro {606 return isMacroEnd(tok)607 }608 return TokenIn(tok, token.EOF, token.COMMENT, token.MACRO)609}610// 解æåé¢é611// å®åæ°åé¢éä¸åä¸è¿ç®612func (p *Parser) parseText() (node ast.MacroLiter) {613 node = &ast.Text{614 Offset: p.pos,615 Kind: p.tok,616 Text: p.lit,617 }618 p.next()619 return620}621func (p *Parser) parseComment() ast.Stmt {622 return &ast.Comment{623 Offset: p.pos,624 Kind: p.tok,625 Text: p.lit,626 }627}628func (p *Parser) parseIf() ast.Stmt {629 node := &ast.IfStmt{From: p.pos}630 return node631}632// 解æå®è¡¨è¾¾å¼633func (p *Parser) parseExpr() (expr ast.MacroLiter) {634 return p.parseExprPrecedence(token.LowestPrec)635}636// 解æ表达å¼637// ä¼å
级è¿ç®è§£æ638func (p *Parser) parseExprPrecedence(prec int) (expr ast.MacroLiter) {639 p.skipWhitespace()640 expr = p.parseOpExpr(prec + 1)641 p.skipWhitespace()642 for p.tok.Precedence() > prec {643 op := p.tok644 offs := p.pos645 p.next()646 p.skipWhitespace()647 y := p.parseOpExpr(prec + 1)648 p.skipWhitespace()649 expr = &ast.BinaryExpr{650 X: expr,651 Offset: offs,652 Op: op,653 Y: y,654 }655 }656 return expr657}658// ( ("-" / "~" / "defined" / "!" ) parseTermExpr )659func (p *Parser) parseOpExpr(prec int) (expr ast.MacroLiter) {660 if prec >= token.UnaryPrec {661 return p.parseUnaryExpr()662 } else {663 return p.parseExprPrecedence(prec + 1)664 }665}666// ( ("-" / "~" / "defined" / "!" ) parseTermExpr )667func (p *Parser) parseUnaryExpr() ast.MacroLiter {668 p.skipWhitespace()669 var expr *ast.UnaryExpr670 var last *ast.UnaryExpr671 for TokenIn(p.tok, token.LNOT, token.DEFINED, token.NOT, token.SUB) {672 offs := p.pos673 op := p.tok674 p.next()675 p.skipWhitespace()676 last = &ast.UnaryExpr{677 Offset: offs,678 Op: op,679 X: nil,680 }681 if expr == nil {682 expr = last683 } else {684 expr.X = last685 }686 }687 if last != nil {688 last.X = p.parseTermExpr()689 return expr690 }691 return p.parseTermExpr()692}693// "(" expr ")"694// / numeric_expression695// / identifier696// / macro_call_expr.697func (p *Parser) parseTermExpr() (expr ast.MacroLiter) {698 p.skipWhitespace()699 switch p.tok {700 case token.LPAREN:701 lp, _, _ := p.expected(token.LPAREN)702 expr = p.parseExpr()703 rp, _, _ := p.expected(token.RPAREN)704 return &ast.ParenExpr{705 Lparen: lp,706 X: expr,707 Rparen: rp,708 }709 case token.INT, token.FLOAT, token.CHAR, token.STRING:710 return p.parseLiteralExpr()711 case token.IDENT:712 return p.parseIdentExpr()713 }714 if p.tok.IsKeyword() {715 return &ast.Ident{716 Offset: p.pos,717 Name: p.lit,718 }719 }720 return &ast.BadExpr{721 Offset: p.pos,722 Token: p.tok,723 Lit: p.lit,724 }725}726// å符类å727// literal_expression =728// integer_literal token.INT729// / float_literal token.FLOAT730// / string token.STRING731// / char token.CHAR732func (p *Parser) parseLiteralExpr() (expr ast.MacroLiter) {733 expr = &ast.LitExpr{734 Offset: p.pos,735 Kind: p.tok,736 Value: p.lit,737 }738 p.next()739 return740}741// ------------ end expr ----------------- //742// è·åä¸ä¸ä¸ªToken743func (p *Parser) next() (pos token.Pos, tok token.Token, lit string) {744 pos, tok, lit = p.pos, p.tok, p.lit745 p.pos, p.tok, p.lit = p.scanner.Scan()746 return747}748// è·åä¸ä¸ä¸ªæ è¯ç¬¦749func (p *Parser) expectedIdent() (pos token.Pos, tok token.Token, lit string) {750 pos, tok, lit = p.pos, p.tok, p.lit751 if isIdent(tok) {752 p.next()753 return754 }755 p.errorf(pos, "expected ident token, got %v", tok)756 return757}758// æ¯å¦ä¸ºæ è¯ç¬¦759func isIdent(tok token.Token) bool {760 return tok == token.IDENT || (tok.IsKeyword() && tok != token.DEFINED)761}762func (p *Parser) expected(typ ...token.Token) (pos token.Pos, tok token.Token, lit string) {763 pos, tok, lit = p.pos, p.tok, p.lit764 if !TokenIn(tok, typ...) {765 p.errorf(pos, "expected %v token, got %v", typ, tok)766 }767 p.next()768 return769}770func TokenNotIn(tok token.Token, typ ...token.Token) bool {771 return !TokenIn(tok, typ...)772}773// å®ç»æ符774func isMacroEnd(tok token.Token) bool {775 return TokenIn(tok, token.EOF, token.NEWLINE, token.COMMENT)776}777func TokenIn(tok token.Token, typ ...token.Token) bool {778 for _, tt := range typ {779 if tok == tt {780 return true781 }782 }783 return false784}785// è·³è¿ç©ºç½å符786// token.BACKSLASH_NEWLINE, token.BLOCK_COMMENT, token.TEXT787func (p *Parser) skipWhitespace() string {788 t := ""789 for (p.tok == token.TEXT && isEmptyText(p.lit)) || TokenIn(p.tok, token.BACKSLASH_NEWLINE, token.BLOCK_COMMENT) {790 t += p.lit791 p.next()792 }793 return t794}795// æ¸
é¤ç©ºç½796func clearBackslash(text string) string {797 t := ""798 l := len(text)799 for i := 0; i < l; i++ {800 b := text[i]801 if b == '\\' && i+1 < l && text[i+1] == '\n' {802 i++803 } else {804 t += string(b)805 }806 }807 return t808}809// å¤ææ¯å¦æ¯ç©ºææ¬810func isEmptyText(text string) bool {811 for _, b := range text {812 switch b {813 case ' ', '\t', '\r':814 default:815 return false816 }817 }818 return true819}820// æ«æå°å®æ«å°¾821func (p *Parser) scanToMacroEnd(needEmpty bool) (pos token.Pos) {822 for !isMacroEnd(p.tok) {823 cur := p.tok824 if needEmpty && !p.isMacroLineEmpty() && cur != token.BACKSLASH_NEWLINE {825 p.errorf(p.pos, "unexpected token %v", p.tok)826 }827 p.next()828 }829 if p.tok == token.NEWLINE {830 pos = p.pos831 p.next()832 return833 }834 return p.pos835}836// å½å为空837func (p *Parser) isMacroLineEmpty() bool {838 if p.tok == token.BLOCK_COMMENT {839 return true840 }841 if p.tok == token.TEXT && isEmptyText(p.lit) {842 return true843 }844 return false845}846// å°è¯æ¾å° token847func (p *Parser) tryNextNotEmpty(tok ...token.Token) (token.Token, bool) {848 pp := p.clone()849 defer p.reset(pp)850 p.skipWhitespace()851 if !isMacroEnd(p.tok) {852 if TokenIn(p.tok, tok...) {853 return p.tok, true854 }855 }856 return 0, false857}858// æ£æ¥ä¸ä¸ä¸ª token859func (p *Parser) nextNotEmptyIs(tok ...token.Token) bool {860 _, ok := p.tryNextNotEmpty(tok...)861 return ok862}863// ä¸ä¸ä¸ªæ¯IDæ è¯ç¬¦864func (p *Parser) nextNotEmptyIsIdent() bool {865 pp := p.clone()866 defer p.reset(pp)867 p.skipWhitespace()868 if !isMacroEnd(p.tok) {869 if isIdent(p.tok) {870 return true871 }872 }873 return false874}875// æ£æ¥ä¸ä¸ä¸ª token876func (p *Parser) tryNext(tok ...token.Token) (token.Token, bool) {877 pp := p.clone()878 defer p.reset(pp)879 if !isMacroEnd(p.tok) {880 if TokenIn(p.tok, tok...) {881 return p.tok, true...
skipWhitespace
Using AI Code Generation
1import (2func main() {3 f, err := parser.ParseFile(fset, "2.go", nil, parser.ParseComments)4 if err != nil {5 log.Fatal(err)6 }7 ast.Inspect(f, func(n ast.Node) bool {8 if n == nil {9 }10 switch x := n.(type) {11 fmt.Printf("%d:%d %s\n", fset.Position(x.Pos()).Line, fset.Position(x.Pos()).Column, x.Name)12 fmt.Printf("%d:%d %s\n", fset.Position(x.Pos()).Line, fset.Position(x.Pos()).Column, x.Value)13 fmt.Printf("%d:%d %s\n", fset.Position(x.Pos()).Line, fset.Position(x.Pos()).Column, x.Op)14 }15 })16}
skipWhitespace
Using AI Code Generation
1import (2func main() {3 f, err := parser.ParseFile(fset, "2.go", nil, parser.ImportsOnly)4 if err != nil {5 }6 fmt.Println("Imports:")7 for _, s := range f.Imports {8 fmt.Println(s.Path.Value)9 }10 fmt.Println("Imports:")11 for _, s := range f.Imports {12 fmt.Println(s.Path.Value)13 }14 fmt.Println("Imports:")15 for _, s := range f.Imports {16 fmt.Println(s.Path.Value)17 }18 fmt.Println("Imports:")19 for _, s := range f.Imports {20 fmt.Println(s.Path.Value)21 }22 fmt.Println("Imports:")23 for _, s := range f.Imports {24 fmt.Println(s.Path.Value)25 }26 fmt.Println("Imports:")27 for _, s := range f.Imports {28 fmt.Println(s.Path.Value)29 }30 fmt.Println("Imports:")31 for _, s := range f.Imports {32 fmt.Println(s.Path.Value)33 }34 fmt.Println("Imports:")35 for _, s := range f.Imports {36 fmt.Println(s.Path.Value)37 }38 fmt.Println("Imports:")39 for _, s := range f.Imports {40 fmt.Println(s.Path.Value)41 }42 fmt.Println("Imports:")43 for _, s := range f.Imports {44 fmt.Println(s
skipWhitespace
Using AI Code Generation
1import (2func main() {3import "fmt"4func main() {5 fmt.Println("hello")6}`7 f, err := parser.ParseFile(fset, "2.go", src, 0)8 if err != nil {9 fmt.Println(err)10 }11 for _, s := range f.Imports {12 fmt.Println(s.Path.Value)13 }14 ast.Inspect(f, func(n ast.Node) bool {15 fn, ok := n.(*ast.FuncDecl)16 if !ok {17 }18 ast.Inspect(fn.Body, func(n ast.Node) bool {19 call, ok := n.(*ast.CallExpr)20 if !ok {21 }22 id, ok := call.Fun.(*ast.Ident)23 if !ok || id.Name != "Println" {24 }25 for _, a := range call.Args {26 lit, ok := a.(*ast.BasicLit)27 if !ok {28 }29 fmt.Println(lit.Value)30 }31 })32 })33}
skipWhitespace
Using AI Code Generation
1import (2func main() {3 fset := token.NewFileSet()4 f, err := parser.ParseFile(fset, "2.go", nil, parser.ImportsOnly)5 if err != nil {6 fmt.Println(err)7 }8 for _, s := range f.Imports {9 fmt.Println(fset.Position(s.Pos()), fset.Position(s.End()))10 }11}
skipWhitespace
Using AI Code Generation
1import (2func main() {3 fset := token.NewFileSet()4 src := []byte(`5import "fmt"6func main() {7 fmt.Println("Hello, playground")8}`)9 f, err := parser.ParseFile(fset, "main.go", src, 0)10 if err != nil {11 fmt.Println(err)12 }13 ast.Print(fset, f)14 fmt.Println("**********************************")15 ast.Inspect(f, func(n ast.Node) bool {16 if n != nil {17 switch x := n.(type) {18 fmt.Println("import:", x.Path.Value)19 }20 }21 })22}
skipWhitespace
Using AI Code Generation
1import (2func main() {3 func main() {4 fmt.Println("Hello World!")5 }`6 file, err := parser.ParseFile(fset, "hello.go", src, parser.ParseComments)7 if err != nil {8 panic(err)9 }10 for _, decl := range file.Decls {11 if fn, ok := decl.(*ast.FuncDecl); ok {12 fmt.Println(fn.Name.Name)13 fmt.Println(fn.Body.Lbrace)14 fmt.Println(fn.Body.Rbrace)15 fmt.Println(fn.Body.List)16 fmt.Println(fn.Body.List[0].Pos())17 fmt.Println(fn.Body.List[0].End())18 fmt.Println(fset.Position(fn.Body.List[0].Pos()))19 fmt.Println(fset.Position(fn.Body.List[0].End()))20 fmt.Println(src[fn.Body.List[0].Pos()-1 : fn.Body.List[0].End()-1])21 }22 }23}
skipWhitespace
Using AI Code Generation
1import (2func main() {3func main() {4 fmt.Println("Hello, 世界")5}`6 fset := token.NewFileSet()7 f, err := parser.ParseFile(fset, "", src, 0)8 if err != nil {9 panic(err)10 }11 ast.Fprint(fset, f, nil)
skipWhitespace
Using AI Code Generation
1import (2func main() {3 input, err := ioutil.ReadFile("1.go")4 if err != nil {5 log.Fatal(err)6 }7 f, err := parser.ParseFile(fset, "1.go", input, 0)8 if err != nil {9 log.Fatal(err)10 }11 ast.Inspect(f, func(n ast.Node) bool {12 switch x := n.(type) {13 fmt.Printf("Function: %s\n", x.Name.Name)14 fmt.Printf("Function body: %s\n", x.Body.List)15 fmt.Printf("Function body: %s\n", x.Body)16 fmt.Printf("Function body: %s\n", x.Body.List[0])17 fmt.Printf("Function body: %s\n", x.Body.List[1])18 fmt.Printf("Function body: %s\n", x.Body.List[2])19 fmt.Printf("Function body: %s\n", x.Body.List[3])20 fmt.Printf("Function body: %s\n", x.Body.List[4])21 fmt.Printf("Function body: %s\n", x.Body.List[5])22 fmt.Printf("Function body: %s\n", x.Body.List[6])23 fmt.Printf("Function body: %s\n", x.Body.List[7])24 fmt.Printf("Function body: %s\n", x.Body.List[8])25 fmt.Printf("Function body: %s\n", x.Body.List[9])
skipWhitespace
Using AI Code Generation
1import java.io.*;2import java.util.Scanner;3import java.util.ArrayList;4import java.util.List;5import java.util.Arrays;6import java.util.Collections;7import java.util.Iterator;8import java.util.NoSuchElementException;9import java.util.Stack;10import java.util.HashMap;11import java.util.Map;12import java.util.HashSet;13import java.util.Set;14import java.util.TreeSet;15import java.util.Comparator;16import java.util.Collection;17import java.util.regex.Pattern;18import java.util.regex.Matcher;19import java.util.stream.Collectors;20import java.util.stream.Stream;21import java.util.stream.IntStream;22import java.util.stream.LongStream;23import java.util.function.Function;24import java.util.function.Predicate;25import java.util.function.Supplier;26import java.util.function.Consumer;27import java.util.function.BiFunction;28import java.util.function.BiConsumer;29import java.util.function.BinaryOperator;30import java.util.function.UnaryOperator;31import java.util.Optional;32import java.util.OptionalInt;33import java.util.OptionalLong;34import java.util.OptionalDouble;35import java.util.concurrent.Callable;36import java.util.concurrent.ForkJoinPool;37import java.util.concurrent.ForkJoinTask;38import java.util.concurrent.RecursiveTask;39import java.util.concurrent.RecursiveAction;40import java.util.concurrent.TimeUnit;41import java.util.concurrent.atomic.AtomicInteger;42import java.util.concurrent.atomic.AtomicLong;43import java.util.concurrent.atomic.AtomicReference;44import java.lang.reflect.Array;45import java.lang.reflect.Field;46import java.lang.reflect.Method;47import java.lang.reflect.Modifier;48import java.lang.reflect.Constructor;49import java.lang.reflect.InvocationTargetException;50import java.lang.reflect.Type;51import java.lang.reflect.ParameterizedType;52import java.lang.reflect.TypeVariable;53import java.lang.reflect.WildcardType;54import java.nio.file.Path;55import java.nio.file.Paths;56import java.nio.file.Files;57import java.nio.file.FileSystems;58import java.nio.file.FileVisitResult;59import java.nio.file.SimpleFileVisitor;60import java.nio.file.attribute.BasicFileAttributes;61import org.w3c.dom.*;62import javax.xml.parsers.*;63import javax.xml.transform.*;64import javax.xml.transform.dom.*;65import javax.xml.transform.stream.*;66{67 public static void main(String[] args) throws Exception68 {69 ast a = new ast();70 File f = new File("input.txt");71 Scanner sc = new Scanner(f);
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!