package parser import ( "go.arsenm.dev/amu/ast" "go.arsenm.dev/amu/scanner" ) // parseList attempts to parse a list func (p *Parser) parseList() *ast.List { // Create new list list := &ast.List{} tok, lit := p.scan() // If token is not WORD or literal is not "=list" if tok != scanner.WORD || lit != "=list" { // Return nil as this list is invalid return nil } tok, lit = p.scan() // If token is not PUNCT or literal is not "[" if tok != scanner.PUNCT || lit != "[" { // Return nil as this list is invalid return nil } tok, lit = p.scan() // If token is not WORD (the name of the function) if tok != scanner.WORD { // Return nil as this list is invalid return nil } list.Type = lit tok, lit = p.scan() // If token is not PUNCT or literal is not "]" if tok != scanner.PUNCT || lit != "]" { // Return nil as this list is invalid return nil } parseLoop: for { // If end of file if tok == scanner.EOF { // Return whatever was parsed so far return list } // Create new list item at level 0 item := ast.ListItem{Level: 0} for { // Scan token tok, lit = p.scan() // If end of file if tok == scanner.EOF { // Return whatever was parsed so far return list } // If token is not punctuation or literal is not "." if tok != scanner.PUNCT || lit != "." { // Break out of loop as this is the end of level break } // Increment item level item.Level++ } for tok != scanner.PUNCT && lit != "." { // If token is WORD and literal is "=end" if tok == scanner.WORD && lit == "=end" { // Scan token tok, lit = p.scan() // If token is not PUNCT and literal is not "[" if tok != scanner.PUNCT && lit != "[" { // Return nil as this is not a valid list return nil } // Scan token tok, lit = p.scan() // If token is not PUNCT and literal is not "]" if tok != scanner.PUNCT && lit != "]" { // Return nil as this is not a valid list return nil } // Add item to list list.Items = append(list.Items, item) // Stop parsing break parseLoop } // If end of file if tok == scanner.EOF { // Return whatever was parsed so far return list } // Unscan character as it will be required for para p.unscan() // Attempt to parse para until one newline encountered para := p.parsePara(1) if para == nil { break } // Add para to item content item.Content = append(item.Content, para) // Scan token for next loop tok, lit = p.scan() // if end of line if tok == scanner.EOL { // Scan again tok, lit = p.scan() } } // If token is part of level if tok == scanner.PUNCT && lit == "." { // Unscan for next level loop p.unscan() } // If no content in item if len(item.Content) == 0 { // Continue to next item continue } // Add item to list items list.Items = append(list.Items, item) } // Return lists return list }