Best Syzkaller code snippet using ast.tryConsume
parser_impl.go
Source:parser_impl.go
...147 p.currentNode().Connect(dslshape.NodePredicateChild, errorNode)148}149// consumeKeyword consumes an expected keyword token or adds an error node.150func (p *sourceParser) consumeKeyword(keyword string) bool {151 if !p.tryConsumeKeyword(keyword) {152 p.emitErrorf("Expected keyword %s, found token %v", keyword, p.currentToken.Kind)153 return false154 }155 return true156}157// tryConsumeKeyword attempts to consume an expected keyword token.158func (p *sourceParser) tryConsumeKeyword(keyword string) bool {159 if !p.isKeyword(keyword) {160 return false161 }162 p.consumeToken()163 return true164}165// cosumeIdentifier consumes an expected identifier token or adds an error node.166func (p *sourceParser) consumeIdentifier() (string, bool) {167 token, ok := p.tryConsume(lexer.TokenTypeIdentifier)168 if !ok {169 p.emitErrorf("Expected identifier, found token %v", p.currentToken.Kind)170 return "", false171 }172 return token.Value, true173}174// consume performs consumption of the next token if it matches any of the given175// types and returns it. If no matching type is found, adds an error node.176func (p *sourceParser) consume(types ...lexer.TokenType) (lexer.Lexeme, bool) {177 token, ok := p.tryConsume(types...)178 if !ok {179 p.emitErrorf("Expected one of: %v, found: %v", types, p.currentToken.Kind)180 }181 return token, ok182}183// tryConsume performs consumption of the next token if it matches any of the given184// types and returns it.185func (p *sourceParser) tryConsume(types ...lexer.TokenType) (lexer.Lexeme, bool) {186 token, found := p.tryConsumeWithComments(types...)187 return token.Lexeme, found188}189// tryConsume performs consumption of the next token if it matches any of the given190// types and returns it.191func (p *sourceParser) tryConsumeWithComments(types ...lexer.TokenType) (commentedLexeme, bool) {192 if p.isToken(types...) {193 token := p.currentToken194 p.consumeToken()195 return token, true196 }197 return commentedLexeme{lexer.Lexeme{198 Kind: lexer.TokenTypeError,199 }, make([]string, 0)}, false200}201// performLeftRecursiveParsing performs left-recursive parsing of a set of operators. This method202// first performs the parsing via the subTryExprFn and then checks for one of the left-recursive203// operator token types found. If none found, the left expression is returned. Otherwise, the204// rightNodeBuilder is called to attempt to construct an operator expression. This method also205// properly handles decoration of the nodes with their proper start and end run locations and206// comments.207func (p *sourceParser) performLeftRecursiveParsing(subTryExprFn tryParserFn, rightNodeBuilder rightNodeConstructor, rightTokenTester lookaheadParserFn, operatorTokens ...lexer.TokenType) (AstNode, bool) {208 var currentLeftToken commentedLexeme209 currentLeftToken = p.currentToken210 // Consume the left side of the expression.211 leftNode, ok := subTryExprFn()212 if !ok {213 return nil, false214 }215 // Check for an operator token. If none found, then we've found just the left side of the216 // expression and so we return that node.217 if !p.isToken(operatorTokens...) {218 return leftNode, true219 }220 // Keep consuming pairs of operators and child expressions until such221 // time as no more can be consumed. We use this loop+custom build rather than recursion222 // because these operators are *left* recursive, not right.223 var currentLeftNode AstNode224 currentLeftNode = leftNode225 for {226 // Check for an operator.227 if !p.isToken(operatorTokens...) {228 break229 }230 // If a lookahead function is defined, check the lookahead for the matched token.231 if rightTokenTester != nil && !rightTokenTester(p.currentToken.Lexeme) {232 break233 }234 // Consume the operator.235 operatorToken, ok := p.tryConsumeWithComments(operatorTokens...)236 if !ok {237 break238 }239 // Consume the right hand expression and build an expression node (if applicable).240 exprNode, ok := rightNodeBuilder(currentLeftNode, operatorToken.Lexeme)241 if !ok {242 p.emitErrorf("Expected right hand expression, found: %v", p.currentToken.Kind)243 return currentLeftNode, true244 }245 p.decorateStartRuneAndComments(exprNode, currentLeftToken)246 p.decorateEndRune(exprNode, p.previousToken)247 currentLeftNode = exprNode248 currentLeftToken = operatorToken249 }250 return currentLeftNode, true251}252// tryConsumeStatementTerminator tries to consume a statement terminator.253func (p *sourceParser) tryConsumeStatementTerminator() (lexer.Lexeme, bool) {254 return p.tryConsume(lexer.TokenTypeSyntheticSemicolon, lexer.TokenTypeSemicolon, lexer.TokenTypeEOF)255}256// consumeStatementTerminator consume a statement terminator.257func (p *sourceParser) consumeStatementTerminator() bool {258 _, ok := p.tryConsumeStatementTerminator()259 if ok {260 return true261 }262 p.emitErrorf("Expected end of statement or definition, found: %s", p.currentToken.Kind)263 return false264}265// binaryOpDefinition represents information a binary operator token and its associated node type.266type binaryOpDefinition struct {267 // The token representing the binary expression's operator.268 BinaryOperatorToken lexer.TokenType269 // The type of node to create for this expression.270 BinaryExpressionNodeType dslshape.NodeType271}272// buildBinaryOperatorExpressionFnTree builds a tree of functions to try to consume a set of binary273// operator expressions.274func (p *sourceParser) buildBinaryOperatorExpressionFnTree(ops []binaryOpDefinition) tryParserFn {275 // Start with a base expression function.276 var currentParseFn tryParserFn277 currentParseFn = func() (AstNode, bool) {278 arrowExpr, ok := p.tryConsumeArrowExpression()279 if !ok {280 return p.tryConsumeBaseExpression()281 }282 return arrowExpr, true283 }284 for i := range ops {285 // Note: We have to reverse this to ensure we have proper precedence.286 currentParseFn = func(operatorInfo binaryOpDefinition, currentFn tryParserFn) tryParserFn {287 return (func() (AstNode, bool) {288 return p.tryConsumeComputeExpression(currentFn, operatorInfo.BinaryOperatorToken, operatorInfo.BinaryExpressionNodeType)289 })290 }(ops[len(ops)-i-1], currentParseFn)291 }292 return currentParseFn293}...
parser.go
Source:parser.go
...35 if p.isToken(lexer.TokenTypeEOF) {36 break Loop37 }38 // Consume a statement terminator if one was found.39 p.tryConsumeStatementTerminator()40 if p.isToken(lexer.TokenTypeEOF) {41 break Loop42 }43 // The top level of the DSL is a set of definitions:44 // definition foobar { ... }45 switch {46 case p.isKeyword("definition"):47 rootNode.Connect(dslshape.NodePredicateChild, p.consumeDefinition())48 default:49 p.emitErrorf("Unexpected token at root level: %v", p.currentToken.Kind)50 break Loop51 }52 }53 return rootNode54}55// consumeDefinition attempts to consume a single schema definition.56// ```definition somedef { ... }````57func (p *sourceParser) consumeDefinition() AstNode {58 defNode := p.startNode(dslshape.NodeTypeDefinition)59 defer p.finishNode()60 // definition ...61 p.consumeKeyword("definition")62 definitionName, ok := p.consumeTypePath()63 if !ok {64 return defNode65 }66 defNode.Decorate(dslshape.NodeDefinitionPredicateName, definitionName)67 // {68 _, ok = p.consume(lexer.TokenTypeLeftBrace)69 if !ok {70 return defNode71 }72 // Relations and permissions.73 for {74 // }75 if _, ok := p.tryConsume(lexer.TokenTypeRightBrace); ok {76 break77 }78 // relation ...79 // permission ...80 switch {81 case p.isKeyword("relation"):82 defNode.Connect(dslshape.NodePredicateChild, p.consumeRelation())83 case p.isKeyword("permission"):84 defNode.Connect(dslshape.NodePredicateChild, p.consumePermission())85 }86 ok := p.consumeStatementTerminator()87 if !ok {88 break89 }90 }91 return defNode92}93// consumeRelation consumes a relation.94// ```relation foo: sometype```95func (p *sourceParser) consumeRelation() AstNode {96 relNode := p.startNode(dslshape.NodeTypeRelation)97 defer p.finishNode()98 // relation ...99 p.consumeKeyword("relation")100 relationName, ok := p.consumeIdentifier()101 if !ok {102 return relNode103 }104 relNode.Decorate(dslshape.NodePredicateName, relationName)105 // :106 _, ok = p.consume(lexer.TokenTypeColon)107 if !ok {108 return relNode109 }110 // Relation allowed type(s).111 relNode.Connect(dslshape.NodeRelationPredicateAllowedTypes, p.consumeTypeReference())112 return relNode113}114// consumeTypeReference consumes a reference to a type or types of relations.115// ```sometype | anothertype | anothertype:* ```116func (p *sourceParser) consumeTypeReference() AstNode {117 refNode := p.startNode(dslshape.NodeTypeTypeReference)118 defer p.finishNode()119 for {120 refNode.Connect(dslshape.NodeTypeReferencePredicateType, p.consumeSpecificType())121 if _, ok := p.tryConsume(lexer.TokenTypePipe); !ok {122 break123 }124 }125 return refNode126}127// consumeSpecificType consumes an identifier as a specific type reference.128func (p *sourceParser) consumeSpecificType() AstNode {129 specificNode := p.startNode(dslshape.NodeTypeSpecificTypeReference)130 defer p.finishNode()131 typeName, ok := p.consumeTypePath()132 if !ok {133 return specificNode134 }135 specificNode.Decorate(dslshape.NodeSpecificReferencePredicateType, typeName)136 // Check for a wildcard137 if _, ok := p.tryConsume(lexer.TokenTypeColon); ok {138 _, ok := p.consume(lexer.TokenTypeStar)139 if !ok {140 return specificNode141 }142 specificNode.Decorate(dslshape.NodeSpecificReferencePredicateWildcard, "true")143 return specificNode144 }145 // Check for a relation specified.146 if _, ok := p.tryConsume(lexer.TokenTypeHash); !ok {147 return specificNode148 }149 // Consume an identifier or an ellipsis.150 consumed, ok := p.consume(lexer.TokenTypeIdentifier, lexer.TokenTypeEllipsis)151 if !ok {152 return specificNode153 }154 specificNode.Decorate(dslshape.NodeSpecificReferencePredicateRelation, consumed.Value)155 return specificNode156}157func (p *sourceParser) consumeTypePath() (string, bool) {158 typeNameOrNamespace, ok := p.consumeIdentifier()159 if !ok {160 return "", false161 }162 _, ok = p.tryConsume(lexer.TokenTypeDiv)163 if !ok {164 return typeNameOrNamespace, true165 }166 typeName, ok := p.consumeIdentifier()167 if !ok {168 return "", false169 }170 return fmt.Sprintf("%s/%s", typeNameOrNamespace, typeName), true171}172// consumePermission consumes a permission.173// ```permission foo = bar + baz```174func (p *sourceParser) consumePermission() AstNode {175 permNode := p.startNode(dslshape.NodeTypePermission)176 defer p.finishNode()177 // permission ...178 p.consumeKeyword("permission")179 permissionName, ok := p.consumeIdentifier()180 if !ok {181 return permNode182 }183 permNode.Decorate(dslshape.NodePredicateName, permissionName)184 // =185 _, ok = p.consume(lexer.TokenTypeEquals)186 if !ok {187 return permNode188 }189 permNode.Connect(dslshape.NodePermissionPredicateComputeExpression, p.consumeComputeExpression())190 return permNode191}192// ComputeExpressionOperators defines the binary operators in precedence order.193var ComputeExpressionOperators = []binaryOpDefinition{194 {lexer.TokenTypeMinus, dslshape.NodeTypeExclusionExpression},195 {lexer.TokenTypeAnd, dslshape.NodeTypeIntersectExpression},196 {lexer.TokenTypePlus, dslshape.NodeTypeUnionExpression},197}198// consumeComputeExpression consumes an expression for computing a permission.199func (p *sourceParser) consumeComputeExpression() AstNode {200 // Compute expressions consist of a set of binary operators, so build a tree with proper201 // precedence.202 binaryParser := p.buildBinaryOperatorExpressionFnTree(ComputeExpressionOperators)203 found, ok := binaryParser()204 if !ok {205 return p.createErrorNodef("Expected compute expression for permission")206 }207 return found208}209// tryConsumeComputeExpression attempts to consume a nested compute expression.210func (p *sourceParser) tryConsumeComputeExpression(subTryExprFn tryParserFn, binaryTokenType lexer.TokenType, nodeType dslshape.NodeType) (AstNode, bool) {211 rightNodeBuilder := func(leftNode AstNode, operatorToken lexer.Lexeme) (AstNode, bool) {212 rightNode, ok := subTryExprFn()213 if !ok {214 return nil, false215 }216 // Create the expression node representing the binary expression.217 exprNode := p.createNode(nodeType)218 exprNode.Connect(dslshape.NodeExpressionPredicateLeftExpr, leftNode)219 exprNode.Connect(dslshape.NodeExpressionPredicateRightExpr, rightNode)220 return exprNode, true221 }222 return p.performLeftRecursiveParsing(subTryExprFn, rightNodeBuilder, nil, binaryTokenType)223}224// tryConsumeArrowExpression attempts to consume an arrow expression.225// ```foo->bar->baz->meh```226func (p *sourceParser) tryConsumeArrowExpression() (AstNode, bool) {227 rightNodeBuilder := func(leftNode AstNode, operatorToken lexer.Lexeme) (AstNode, bool) {228 rightNode, ok := p.tryConsumeBaseExpression()229 if !ok {230 return nil, false231 }232 // Create the expression node representing the binary expression.233 exprNode := p.createNode(dslshape.NodeTypeArrowExpression)234 exprNode.Connect(dslshape.NodeExpressionPredicateLeftExpr, leftNode)235 exprNode.Connect(dslshape.NodeExpressionPredicateRightExpr, rightNode)236 return exprNode, true237 }238 return p.performLeftRecursiveParsing(p.tryConsumeIdentifierLiteral, rightNodeBuilder, nil, lexer.TokenTypeRightArrow)239}240// tryConsumeBaseExpression attempts to consume base compute expressions (identifiers, parenthesis).241// ```(foo + bar)```242// ```(foo)```243// ```foo```244// ```nil```245func (p *sourceParser) tryConsumeBaseExpression() (AstNode, bool) {246 switch {247 // Nested expression.248 case p.isToken(lexer.TokenTypeLeftParen):249 comments := p.currentToken.comments250 p.consume(lexer.TokenTypeLeftParen)251 exprNode := p.consumeComputeExpression()252 p.consume(lexer.TokenTypeRightParen)253 // Attach any comments found to the consumed expression.254 p.decorateComments(exprNode, comments)255 return exprNode, true256 // Nil expression.257 case p.isKeyword("nil"):258 return p.tryConsumeNilExpression()259 // Identifier.260 case p.isToken(lexer.TokenTypeIdentifier):261 return p.tryConsumeIdentifierLiteral()262 }263 return nil, false264}265// tryConsumeIdentifierLiteral attempts to consume an identifier as a literal266// expression.267//268// ```foo```269func (p *sourceParser) tryConsumeIdentifierLiteral() (AstNode, bool) {270 if !p.isToken(lexer.TokenTypeIdentifier) {271 return nil, false272 }273 identNode := p.startNode(dslshape.NodeTypeIdentifier)274 defer p.finishNode()275 identifier, _ := p.consumeIdentifier()276 identNode.Decorate(dslshape.NodeIdentiferPredicateValue, identifier)277 return identNode, true278}279func (p *sourceParser) tryConsumeNilExpression() (AstNode, bool) {280 if !p.isKeyword("nil") {281 return nil, false282 }283 node := p.startNode(dslshape.NodeTypeNilExpression)284 p.consumeKeyword("nil")285 defer p.finishNode()286 return node, true287}...
parser_rules.go
Source:parser_rules.go
...63func (p *sourceParser) consumeDeclaration() AstNode {64 declNode := p.startNode(NodeTypeDeclaration)65 defer p.finishNode()66 // Consume any annotations.67 p.tryConsumeAnnotations(declNode, NodePredicateDeclarationAnnotation)68 // Consume the type of declaration.69 if !p.consumeKeyword("interface") {70 return declNode71 }72 declNode.Decorate(NodePredicateDeclarationKind, "interface")73 // Consume the name of the declaration.74 declNode.Decorate(NodePredicateDeclarationName, p.consumeIdentifier())75 // Check for (optional) inheritance.76 if _, ok := p.tryConsume(tokenTypeColon); ok {77 declNode.Decorate(NodePredicateDeclarationParentType, p.consumeIdentifier())78 }79 // {80 p.consume(tokenTypeLeftBrace)81 // Members and custom operations (if any).82loop:83 for {84 if p.isToken(tokenTypeRightBrace) {85 break86 }87 if p.isKeyword("serializer") || p.isKeyword("jsonifier") {88 customOpNode := p.startNode(NodeTypeCustomOp)89 customOpNode.Decorate(NodePredicateCustomOpName, p.currentToken.value)90 p.consume(tokenTypeKeyword)91 _, ok := p.consume(tokenTypeSemicolon)92 p.finishNode()93 declNode.Connect(NodePredicateDeclarationCustomOperation, customOpNode)94 if !ok {95 break loop96 }97 continue98 }99 declNode.Connect(NodePredicateDeclarationMember, p.consumeMember())100 if _, ok := p.consume(tokenTypeSemicolon); !ok {101 break102 }103 }104 // };105 p.consume(tokenTypeRightBrace)106 p.consume(tokenTypeSemicolon)107 return declNode108}109// consumeMember attempts to consume a member definition in a declaration.110func (p *sourceParser) consumeMember() AstNode {111 memberNode := p.startNode(NodeTypeMember)112 defer p.finishNode()113 var isAttribute = false114 // annotations115 p.tryConsumeAnnotations(memberNode, NodePredicateMemberAnnotation)116 // getter/setter117 var specialization = ""118 if p.isKeyword("getter") || p.isKeyword("setter") {119 consumed, _ := p.consume(tokenTypeKeyword)120 specialization = consumed.value121 memberNode.Decorate(NodePredicateMemberSpecialization, specialization)122 }123 // static readonly attribute124 if p.tryConsumeKeyword("static") {125 memberNode.Decorate(NodePredicateMemberStatic, "true")126 }127 if p.tryConsumeKeyword("readonly") {128 memberNode.Decorate(NodePredicateMemberReadonly, "true")129 }130 if p.tryConsumeKeyword("attribute") {131 isAttribute = true132 memberNode.Decorate(NodePredicateMemberAttribute, "true")133 }134 // Consume the type of the member.135 memberNode.Decorate(NodePredicateMemberType, p.consumeType())136 // Consume the member's name.137 if specialization == "" {138 memberNode.Decorate(NodePredicateMemberName, p.consumeIdentifier())139 }140 // If not an attribute, consume the parameters of the member.141 if !isAttribute {142 p.consumeParameters(memberNode, NodePredicateMemberParameter)143 }144 return memberNode145}146// tryConsumeAnnotations consumes any annotations found on the parent node.147func (p *sourceParser) tryConsumeAnnotations(parentNode AstNode, predicate string) {148 for {149 // [150 if _, ok := p.tryConsume(tokenTypeLeftBracket); !ok {151 return152 }153 for {154 // Foo()155 parentNode.Connect(predicate, p.consumeAnnotationPart())156 // ,157 if _, ok := p.tryConsume(tokenTypeComma); !ok {158 break159 }160 }161 // ]162 if _, ok := p.consume(tokenTypeRightBracket); !ok {163 return164 }165 }166}167// consumeAnnotationPart consumes an annotation, as found within a set of brackets `[]`.168func (p *sourceParser) consumeAnnotationPart() AstNode {169 annotationNode := p.startNode(NodeTypeAnnotation)170 defer p.finishNode()171 // Consume the name of the annotation.172 annotationNode.Decorate(NodePredicateAnnotationName, p.consumeIdentifier())173 // Consume (optional) value.174 if _, ok := p.tryConsume(tokenTypeEquals); ok {175 annotationNode.Decorate(NodePredicateAnnotationDefinedValue, p.consumeIdentifier())176 }177 // Consume (optional) parameters.178 if p.isToken(tokenTypeLeftParen) {179 p.consumeParameters(annotationNode, NodePredicateAnnotationParameter)180 }181 return annotationNode182}183// expandedTypeKeywords defines the keywords that form the prefixes for expanded types:184// two-identifier type names.185var expandedTypeKeywords = map[string][]string{186 "unsigned": []string{"short", "long"},187 "long": []string{"long"},188 "unrestricted": []string{"float", "double"},189}190// consumeType attempts to consume a type (identifier (with optional ?) or 'any').191func (p *sourceParser) consumeType() string {192 if p.tryConsumeKeyword("any") {193 return "any"194 }195 var typeName = ""196 identifier := p.consumeIdentifier()197 typeName += identifier198 // If the identifier is the beginning of a possible expanded type name, check for the199 // secondary portion.200 if secondaries, ok := expandedTypeKeywords[identifier]; ok {201 for _, secondary := range secondaries {202 if p.isToken(tokenTypeIdentifier) && p.currentToken.value == secondary {203 typeName += " " + secondary204 p.consume(tokenTypeIdentifier)205 break206 }207 }208 }209 if _, ok := p.tryConsume(tokenTypeQuestionMark); ok {210 return typeName + "?"211 } else {212 return typeName213 }214}215// consumeParameter attempts to consume a parameter.216func (p *sourceParser) consumeParameter() AstNode {217 paramNode := p.startNode(NodeTypeParameter)218 defer p.finishNode()219 // optional220 if p.tryConsumeKeyword("optional") {221 paramNode.Decorate(NodePredicateParameterOptional, "true")222 }223 // Consume the parameter's type.224 paramNode.Decorate(NodePredicateParameterType, p.consumeType())225 // Consume the parameter's name.226 paramNode.Decorate(NodePredicateParameterName, p.consumeIdentifier())227 return paramNode228}229// consumeParameters attempts to consume a set of parameters.230func (p *sourceParser) consumeParameters(parentNode AstNode, predicate string) {231 p.consume(tokenTypeLeftParen)232 if _, ok := p.tryConsume(tokenTypeRightParen); ok {233 return234 }235 for {236 parentNode.Connect(predicate, p.consumeParameter())237 if _, ok := p.tryConsume(tokenTypeRightParen); ok {238 return239 }240 if _, ok := p.consume(tokenTypeComma); !ok {241 return242 }243 }244}245// consumeImplementation attempts to consume an implementation definition.246func (p *sourceParser) consumeImplementation() AstNode {247 implNode := p.startNode(NodeTypeImplementation)248 defer p.finishNode()249 // identifier250 implNode.Decorate(NodePredicateImplementationName, p.consumeIdentifier())251 // implements...
tryConsume
Using AI Code Generation
1import (2func main() {3 f, err := parser.ParseFile(fset, "2.go", nil, parser.ImportsOnly)4 if err != nil {5 fmt.Println(err)6 }7 for _, s := range f.Imports {8 fmt.Println(s.Path.Value)9 }10}11import (12func main() {13 f, err := parser.ParseFile(fset, "3.go", nil, 0)14 if err != nil {15 fmt.Println(err)16 }17 ast.Print(fset, f)18}
tryConsume
Using AI Code Generation
1import (2func main() {3func main() {4}5 fset := token.NewFileSet()6 f, err := parser.ParseFile(fset, "src.go", src, parser.ParseComments)7 if err != nil {8 log.Fatal(err)9 }10 ast.Inspect(f, func(n ast.Node) bool {11 if x, ok := n.(*ast.AssignStmt); ok {12 if len(x.Lhs) == 1 && len(x.Rhs) == 1 {13 if ident, ok := x.Lhs[0].(*ast.Ident); ok {14 if ident.Obj == nil || ident.Obj.Kind != ast.Var {15 }16 }17 }18 fmt.Printf("%s19", fset.Position(x.TokPos))20 }21 })22}23import (24func main() {25func main() {26}27 fset := token.NewFileSet()28 f, err := parser.ParseFile(fset, "src.go", src, parser.ParseComments)29 if err != nil {30 log.Fatal(err)31 }32 ast.Inspect(f, func(n ast.Node) bool {33 if x, ok := n.(*ast.AssignStmt); ok {34 if len(x.Lhs) == 1 && len(x.Rhs) == 1 {35 if ident, ok := x.Lhs[0].(*ast.Ident); ok {36 if ident.Obj == nil || ident.Obj.Kind != ast.Var {37 }38 }39 }40 fmt.Printf("%s41", fset.Position(x.TokPos))42 }43 })44}
tryConsume
Using AI Code Generation
1func main() {2 a := ast.New(s)3 a.TryConsume("a")4 a.TryConsume("b")5 a.TryConsume("c")6 a.TryConsume("d")7 fmt.Println(a)8}9func main() {10 a := ast.New(s)11 a.TryConsume("a")12 a.TryConsume("b")13 a.TryConsume("c")14 a.TryConsume("d")15 fmt.Println(a)16}17func main() {18 a := ast.New(s)19 a.TryConsume("a")20 a.TryConsume("b")21 a.TryConsume("c")22 a.TryConsume("d")23 fmt.Println(a)24}25func main() {26 a := ast.New(s)27 a.TryConsume("a")28 a.TryConsume("b")29 a.TryConsume("c")30 a.TryConsume("d")31 fmt.Println(a)32}33func main() {34 a := ast.New(s)35 a.TryConsume("a")36 a.TryConsume("b")37 a.TryConsume("c")38 a.TryConsume("d")39 fmt.Println(a)40}41func main() {42 a := ast.New(s)43 a.TryConsume("a")44 a.TryConsume("b")45 a.TryConsume("c")46 a.TryConsume("d")47 fmt.Println(a)48}49func main() {50 a := ast.New(s)
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!!