diff --git a/parser/additional_parser_test.go b/parser/additional_parser_test.go index 0fda572..c5e8b18 100644 --- a/parser/additional_parser_test.go +++ b/parser/additional_parser_test.go @@ -2,6 +2,7 @@ package parser import ( "errors" + "fmt" "io" "strings" "testing" @@ -375,3 +376,140 @@ func TestStreamingLexerSingleCharOperators(t *testing.T) { } } } + +func TestParseExpr(t *testing.T) { + tests := []struct { + name string + input string + wantErr bool + }{ + { + name: "simple integer", + input: "42", + wantErr: false, + }, + { + name: "simple arithmetic", + input: "2 + 3", + wantErr: false, + }, + { + name: "complex arithmetic", + input: "2 + 3 * 4", + wantErr: false, + }, + { + name: "boolean expression", + input: "(x > 5) && (y < 10)", + wantErr: false, + }, + { + name: "string literal", + input: `"hello world"`, + wantErr: false, + }, + { + name: "list literal", + input: "{1, 2, 3, 4, 5}", + wantErr: false, + }, + { + name: "function call", + input: `strcat("Hello", " ", "World")`, + wantErr: false, + }, + { + name: "conditional expression", + input: `x > 0 ? "positive" : "non-positive"`, + wantErr: false, + }, + { + name: "attribute reference", + input: "MY.attr", + wantErr: false, + }, + { + name: "boolean literal", + input: "true", + wantErr: false, + }, + { + name: "undefined literal", + input: "undefined", + wantErr: false, + }, + { + name: "error literal", + input: "error", + wantErr: false, + }, + { + name: "record literal", + input: "[a = 1; b = 2]", + wantErr: false, + }, + { + name: "nested expression", + input: "((1 + 2) * (3 + 4))", + wantErr: false, + }, + { + name: "syntax error", + input: "2 + +", + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + expr, err := ParseExpr(tt.input) + if tt.wantErr { + if err == nil { + t.Fatalf("ParseExpr(%q) expected error, got nil", tt.input) + } + return + } + if err != nil { + t.Fatalf("ParseExpr(%q) unexpected error: %v", tt.input, err) + } + if expr == nil { + t.Fatalf("ParseExpr(%q) returned nil expression", tt.input) + } + // Verify it implements ast.Expr interface + if _, ok := expr.(ast.Expr); !ok { + t.Fatalf("ParseExpr(%q) result does not implement ast.Expr", tt.input) + } + }) + } +} + +func TestParseExprTypeChecking(t *testing.T) { + // Test that ParseExpr returns different types for different inputs + tests := []struct { + name string + input string + expectedTyp string + }{ + {"integer", "42", "*ast.IntegerLiteral"}, + {"real", "3.14", "*ast.RealLiteral"}, + {"string", `"hello"`, "*ast.StringLiteral"}, + {"boolean", "true", "*ast.BooleanLiteral"}, + {"list", "{1, 2}", "*ast.ListLiteral"}, + {"binary op", "1 + 2", "*ast.BinaryOp"}, + {"attribute ref", "x", "*ast.AttributeReference"}, + {"function call", "func()", "*ast.FunctionCall"}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + expr, err := ParseExpr(tt.input) + if err != nil { + t.Fatalf("ParseExpr(%q) unexpected error: %v", tt.input, err) + } + typeName := fmt.Sprintf("%T", expr) + if typeName != tt.expectedTyp { + t.Fatalf("ParseExpr(%q) returned type %s, want %s", tt.input, typeName, tt.expectedTyp) + } + }) + } +} diff --git a/parser/classad.y b/parser/classad.y index b3463a4..1e4d6c3 100644 --- a/parser/classad.y +++ b/parser/classad.y @@ -59,6 +59,12 @@ start lex.SetResult($1) } } + | expr + { + if lex, ok := yylex.(interface{ SetResult(ast.Node) }); ok { + lex.SetResult($1) + } + } ; classad diff --git a/parser/parser.go b/parser/parser.go index 4439cac..37bf144 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -10,7 +10,8 @@ import ( "github.com/PelicanPlatform/classad/ast" ) -// Parse parses a ClassAd expression string and returns the AST. +// Parse parses a ClassAd or expression string and returns the AST. +// For ClassAd-only parsing, use ParseClassAd. For expression-only parsing, use ParseExpr. func Parse(input string) (ast.Node, error) { lex := NewLexer(input) yyParse(lex) @@ -18,6 +19,7 @@ func Parse(input string) (ast.Node, error) { } // ParseClassAd parses a ClassAd and returns a ClassAd AST node. +// Returns an error if the input is not a valid ClassAd (e.g., if it's a bare expression). func ParseClassAd(input string) (*ast.ClassAd, error) { node, err := Parse(input) if err != nil { @@ -26,7 +28,20 @@ func ParseClassAd(input string) (*ast.ClassAd, error) { if classad, ok := node.(*ast.ClassAd); ok { return classad, nil } - return nil, nil + return nil, fmt.Errorf("parsed input is not a ClassAd, got %T", node) +} + +// ParseExpr parses an expression string and returns the expression AST. +// Returns an error if the input is not a valid expression. +func ParseExpr(input string) (ast.Expr, error) { + node, err := Parse(input) + if err != nil { + return nil, err + } + if expr, ok := node.(ast.Expr); ok { + return expr, nil + } + return nil, fmt.Errorf("parsed input is not an expression, got %T", node) } // ReaderParser parses consecutive ClassAds from a buffered reader without diff --git a/parser/y.go b/parser/y.go index 5402020..bc33866 100644 --- a/parser/y.go +++ b/parser/y.go @@ -1,13 +1,15 @@ -// Code generated by goyacc -v y.output -o parser/y.go -p yy parser/classad.y. DO NOT EDIT. +// Code generated by goyacc -o parser/y.go -p yy parser/classad.y. DO NOT EDIT. //line parser/classad.y:2 package parser -import ( - __yyfmt__ "fmt" +import __yyfmt__ "fmt" + +//line parser/classad.y:2 +import ( "github.com/PelicanPlatform/classad/ast" -) //line parser/classad.y:2 +) //line parser/classad.y:10 type yySymType struct { @@ -99,104 +101,112 @@ const yyEofCode = 1 const yyErrCode = 2 const yyInitialStackSize = 16 -//line parser/classad.y:267 +//line parser/classad.y:273 //line yacctab:1 var yyExca = [...]int8{ -1, 1, 1, -1, -2, 0, + -1, 35, + 1, 4, + -2, 6, + -1, 72, + 1, 3, + -2, 5, } const yyPrivate = 57344 -const yyLast = 130 +const yyLast = 144 var yyAct = [...]int8{ - 75, 13, 73, 23, 21, 18, 19, 106, 24, 17, - 22, 12, 105, 111, 31, 38, 36, 37, 39, 40, - 41, 15, 79, 104, 10, 20, 107, 9, 8, 9, - 110, 71, 3, 16, 72, 67, 68, 69, 70, 27, - 26, 65, 66, 48, 78, 28, 29, 4, 42, 33, - 62, 63, 64, 83, 34, 84, 82, 7, 89, 90, - 91, 92, 7, 47, 96, 97, 80, 102, 93, 94, - 95, 98, 99, 100, 103, 85, 86, 87, 88, 81, - 46, 109, 108, 31, 38, 36, 37, 39, 40, 41, - 76, 60, 61, 77, 57, 58, 59, 45, 5, 53, - 54, 55, 56, 49, 50, 51, 52, 112, 27, 26, - 113, 43, 6, 44, 28, 29, 101, 42, 33, 7, - 1, 74, 11, 34, 14, 25, 30, 32, 35, 2, + 71, 3, 5, 36, 69, 34, 12, 15, 16, 23, + 30, 28, 29, 31, 32, 33, 105, 76, 104, 112, + 103, 11, 111, 73, 110, 74, 68, 62, 64, 65, + 66, 10, 8, 13, 19, 18, 72, 73, 14, 75, + 20, 21, 37, 63, 25, 67, 9, 60, 61, 26, + 43, 82, 83, 84, 85, 23, 30, 28, 29, 31, + 32, 33, 99, 93, 94, 81, 95, 96, 97, 100, + 7, 37, 102, 78, 80, 107, 42, 106, 101, 109, + 19, 18, 86, 87, 88, 89, 20, 21, 79, 63, + 25, 90, 91, 92, 40, 26, 23, 30, 28, 29, + 31, 32, 33, 57, 58, 59, 113, 35, 55, 56, + 77, 114, 52, 53, 54, 48, 49, 50, 51, 41, + 108, 19, 18, 44, 45, 46, 47, 20, 21, 37, + 4, 25, 38, 98, 39, 1, 26, 70, 6, 17, + 22, 24, 27, 2, } var yyPact = [...]int16{ - -6, -1000, -1000, 58, -12, -1000, -1000, -18, -1000, 115, - 79, -1000, -1000, -1000, 100, 83, 65, 47, 26, 85, - 77, 68, 62, 19, -1000, 4, 79, 79, 79, 79, - -1000, -8, -1000, 79, 79, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, 53, 10, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 112, 79, -1000, -1000, -1000, - -1000, 79, -20, -33, -39, -1000, -14, -1000, 70, 79, - 83, 65, 47, 26, 85, 77, 77, 77, 77, 68, - 68, 68, 68, 62, 62, 62, 19, 19, -1000, -1000, - -1000, -1000, -10, -30, -1000, -1000, 79, -1000, 79, -1000, - -1000, -1000, -1000, -1000, + 92, -1000, -1000, -1000, 67, -1000, 121, 80, 104, 60, + 33, 105, 93, 86, 79, 72, -1000, 10, 51, 51, + 51, 51, -1000, 6, -1000, 51, 51, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -4, -1000, -1000, -17, 5, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 129, 51, -1000, 38, -1000, -1000, -1000, 51, -23, -27, + -30, -1000, -1000, 125, 51, 108, 51, 80, 104, 60, + 33, 105, 93, 93, 93, 93, 86, 86, 86, 86, + 79, 79, 79, 72, 72, -1000, -1000, -1000, -1000, -16, + -18, -1000, -24, -1000, -1000, 51, -1000, -1000, 51, -1000, + -1000, -1000, -1000, -1000, -1000, } var yyPgo = [...]uint8{ - 0, 129, 128, 47, 112, 0, 127, 126, 125, 8, - 3, 10, 4, 25, 6, 5, 9, 33, 21, 124, - 1, 121, 2, 120, + 0, 143, 142, 5, 3, 0, 141, 140, 139, 8, + 7, 38, 33, 6, 21, 31, 46, 32, 70, 138, + 2, 137, 4, 135, } var yyR1 = [...]int8{ - 0, 23, 1, 1, 2, 2, 3, 3, 3, 4, - 5, 20, 20, 20, 19, 19, 18, 18, 17, 17, - 16, 16, 15, 15, 14, 14, 14, 14, 14, 13, - 13, 13, 13, 13, 12, 12, 12, 12, 11, 11, - 11, 10, 10, 10, 10, 9, 9, 9, 9, 9, - 8, 8, 8, 8, 7, 7, 7, 7, 7, 6, - 6, 6, 6, 6, 6, 22, 22, 21, 21, + 0, 23, 23, 1, 1, 2, 2, 3, 3, 3, + 4, 5, 20, 20, 20, 19, 19, 18, 18, 17, + 17, 16, 16, 15, 15, 14, 14, 14, 14, 14, + 13, 13, 13, 13, 13, 12, 12, 12, 12, 11, + 11, 11, 10, 10, 10, 10, 9, 9, 9, 9, + 9, 8, 8, 8, 8, 7, 7, 7, 7, 7, + 6, 6, 6, 6, 6, 6, 22, 22, 21, 21, } var yyR2 = [...]int8{ - 0, 1, 3, 2, 3, 2, 1, 3, 2, 3, - 1, 1, 5, 4, 1, 3, 1, 3, 1, 3, - 1, 3, 1, 3, 1, 3, 3, 3, 3, 1, - 3, 3, 3, 3, 1, 3, 3, 3, 1, 3, - 3, 1, 3, 3, 3, 1, 2, 2, 2, 2, - 1, 3, 4, 4, 1, 1, 3, 3, 1, 1, - 1, 1, 1, 1, 1, 0, 1, 1, 3, + 0, 1, 1, 3, 2, 3, 2, 1, 3, 2, + 3, 1, 1, 5, 4, 1, 3, 1, 3, 1, + 3, 1, 3, 1, 3, 1, 3, 3, 3, 3, + 1, 3, 3, 3, 3, 1, 3, 3, 3, 1, + 3, 3, 1, 3, 3, 3, 1, 2, 2, 2, + 2, 1, 3, 4, 4, 1, 1, 3, 3, 1, + 1, 1, 1, 1, 1, 1, 0, 1, 1, 3, } var yyChk = [...]int16{ - -1000, -23, -1, 38, -3, 40, -4, 4, 40, 41, - 42, -4, -5, -20, -19, -18, -17, -16, -15, -14, - -13, -12, -11, -10, -9, -8, 30, 29, 35, 36, - -7, 4, -6, 39, 44, -2, 6, 7, 5, 8, - 9, 10, 38, 11, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, - 29, 30, 31, 32, 33, 37, 38, -9, -9, -9, - -9, 39, -5, -22, -21, -5, -3, 40, -5, 12, - -18, -17, -16, -15, -14, -13, -13, -13, -13, -12, - -12, -12, -12, -11, -11, -11, -10, -10, -9, -9, - -9, 4, -5, -22, 43, 45, 46, 40, 12, -20, - 40, 43, -5, -20, + -1000, -23, -1, -5, 38, -20, -19, -18, -17, -16, + -15, -14, -13, -12, -11, -10, -9, -8, 30, 29, + 35, 36, -7, 4, -6, 39, 44, -2, 6, 7, + 5, 8, 9, 10, -3, 40, -4, 4, 11, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 37, 38, -9, 38, -9, -9, -9, 39, -5, -22, + -21, -5, 40, 41, 42, -5, 12, -18, -17, -16, + -15, -14, -13, -13, -13, -13, -12, -12, -12, -12, + -11, -11, -11, -10, -10, -9, -9, -9, 4, -5, + -3, 40, -22, 43, 45, 46, -4, -5, 12, -20, + 40, 40, 43, -5, -20, } var yyDef = [...]int8{ - 0, -2, 1, 0, 0, 3, 6, 0, 2, 8, - 0, 7, 9, 10, 11, 14, 16, 18, 20, 22, - 24, 29, 34, 38, 41, 45, 0, 0, 0, 0, - 50, 55, 54, 0, 65, 58, 59, 60, 61, 62, - 63, 64, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -2, 1, 2, 0, 11, 12, 15, 17, 19, + 21, 23, 25, 30, 35, 39, 42, 46, 0, 0, + 0, 0, 51, 56, 55, 0, 66, 59, 60, 61, + 62, 63, 64, 65, 0, -2, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 46, 47, 48, - 49, 65, 0, 0, 66, 67, 0, 5, 0, 0, - 15, 17, 19, 21, 23, 25, 26, 27, 28, 30, - 31, 32, 33, 35, 36, 37, 39, 40, 42, 43, - 44, 51, 0, 0, 56, 57, 0, 4, 0, 13, - 52, 53, 68, 12, + 0, 0, 47, 0, 48, 49, 50, 66, 0, 0, + 67, 68, -2, 9, 0, 0, 0, 16, 18, 20, + 22, 24, 26, 27, 28, 29, 31, 32, 33, 34, + 36, 37, 38, 40, 41, 43, 44, 45, 52, 0, + 0, 6, 0, 57, 58, 0, 8, 10, 0, 14, + 53, 5, 54, 69, 13, } var yyTok1 = [...]int8{ @@ -571,405 +581,413 @@ yydefault: } } case 2: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser/classad.y:63 + { + if lex, ok := yylex.(interface{ SetResult(ast.Node) }); ok { + lex.SetResult(yyDollar[1].expr) + } + } + case 3: yyDollar = yyS[yypt-3 : yypt+1] -//line parser/classad.y:66 +//line parser/classad.y:72 { yyVAL.classad = &ast.ClassAd{Attributes: yyDollar[2].attrs} } - case 3: + case 4: yyDollar = yyS[yypt-2 : yypt+1] -//line parser/classad.y:68 +//line parser/classad.y:74 { yyVAL.classad = &ast.ClassAd{Attributes: []*ast.AttributeAssignment{}} } - case 4: + case 5: yyDollar = yyS[yypt-3 : yypt+1] -//line parser/classad.y:73 +//line parser/classad.y:79 { yyVAL.classad = &ast.ClassAd{Attributes: yyDollar[2].attrs} } - case 5: + case 6: yyDollar = yyS[yypt-2 : yypt+1] -//line parser/classad.y:75 +//line parser/classad.y:81 { yyVAL.classad = &ast.ClassAd{Attributes: []*ast.AttributeAssignment{}} } - case 6: + case 7: yyDollar = yyS[yypt-1 : yypt+1] -//line parser/classad.y:80 +//line parser/classad.y:86 { yyVAL.attrs = []*ast.AttributeAssignment{yyDollar[1].attr} } - case 7: + case 8: yyDollar = yyS[yypt-3 : yypt+1] -//line parser/classad.y:82 +//line parser/classad.y:88 { yyVAL.attrs = append(yyDollar[1].attrs, yyDollar[3].attr) } - case 8: + case 9: yyDollar = yyS[yypt-2 : yypt+1] -//line parser/classad.y:84 +//line parser/classad.y:90 { yyVAL.attrs = yyDollar[1].attrs } - case 9: + case 10: yyDollar = yyS[yypt-3 : yypt+1] -//line parser/classad.y:89 +//line parser/classad.y:95 { yyVAL.attr = &ast.AttributeAssignment{Name: yyDollar[1].str, Value: yyDollar[3].expr} } - case 10: + case 11: yyDollar = yyS[yypt-1 : yypt+1] -//line parser/classad.y:94 +//line parser/classad.y:100 { yyVAL.expr = yyDollar[1].expr } - case 11: + case 12: yyDollar = yyS[yypt-1 : yypt+1] -//line parser/classad.y:99 +//line parser/classad.y:105 { yyVAL.expr = yyDollar[1].expr } - case 12: + case 13: yyDollar = yyS[yypt-5 : yypt+1] -//line parser/classad.y:101 +//line parser/classad.y:107 { yyVAL.expr = &ast.ConditionalExpr{Condition: yyDollar[1].expr, TrueExpr: yyDollar[3].expr, FalseExpr: yyDollar[5].expr} } - case 13: + case 14: yyDollar = yyS[yypt-4 : yypt+1] -//line parser/classad.y:103 +//line parser/classad.y:109 { yyVAL.expr = &ast.ElvisExpr{Left: yyDollar[1].expr, Right: yyDollar[4].expr} } - case 14: + case 15: yyDollar = yyS[yypt-1 : yypt+1] -//line parser/classad.y:108 +//line parser/classad.y:114 { yyVAL.expr = yyDollar[1].expr } - case 15: + case 16: yyDollar = yyS[yypt-3 : yypt+1] -//line parser/classad.y:110 +//line parser/classad.y:116 { yyVAL.expr = &ast.BinaryOp{Op: "||", Left: yyDollar[1].expr, Right: yyDollar[3].expr} } - case 16: + case 17: yyDollar = yyS[yypt-1 : yypt+1] -//line parser/classad.y:115 +//line parser/classad.y:121 { yyVAL.expr = yyDollar[1].expr } - case 17: + case 18: yyDollar = yyS[yypt-3 : yypt+1] -//line parser/classad.y:117 +//line parser/classad.y:123 { yyVAL.expr = &ast.BinaryOp{Op: "&&", Left: yyDollar[1].expr, Right: yyDollar[3].expr} } - case 18: + case 19: yyDollar = yyS[yypt-1 : yypt+1] -//line parser/classad.y:122 +//line parser/classad.y:128 { yyVAL.expr = yyDollar[1].expr } - case 19: + case 20: yyDollar = yyS[yypt-3 : yypt+1] -//line parser/classad.y:124 +//line parser/classad.y:130 { yyVAL.expr = &ast.BinaryOp{Op: "|", Left: yyDollar[1].expr, Right: yyDollar[3].expr} } - case 20: + case 21: yyDollar = yyS[yypt-1 : yypt+1] -//line parser/classad.y:129 +//line parser/classad.y:135 { yyVAL.expr = yyDollar[1].expr } - case 21: + case 22: yyDollar = yyS[yypt-3 : yypt+1] -//line parser/classad.y:131 +//line parser/classad.y:137 { yyVAL.expr = &ast.BinaryOp{Op: "^", Left: yyDollar[1].expr, Right: yyDollar[3].expr} } - case 22: + case 23: yyDollar = yyS[yypt-1 : yypt+1] -//line parser/classad.y:136 +//line parser/classad.y:142 { yyVAL.expr = yyDollar[1].expr } - case 23: + case 24: yyDollar = yyS[yypt-3 : yypt+1] -//line parser/classad.y:138 +//line parser/classad.y:144 { yyVAL.expr = &ast.BinaryOp{Op: "&", Left: yyDollar[1].expr, Right: yyDollar[3].expr} } - case 24: + case 25: yyDollar = yyS[yypt-1 : yypt+1] -//line parser/classad.y:143 +//line parser/classad.y:149 { yyVAL.expr = yyDollar[1].expr } - case 25: + case 26: yyDollar = yyS[yypt-3 : yypt+1] -//line parser/classad.y:145 +//line parser/classad.y:151 { yyVAL.expr = &ast.BinaryOp{Op: "==", Left: yyDollar[1].expr, Right: yyDollar[3].expr} } - case 26: + case 27: yyDollar = yyS[yypt-3 : yypt+1] -//line parser/classad.y:147 +//line parser/classad.y:153 { yyVAL.expr = &ast.BinaryOp{Op: "!=", Left: yyDollar[1].expr, Right: yyDollar[3].expr} } - case 27: + case 28: yyDollar = yyS[yypt-3 : yypt+1] -//line parser/classad.y:149 +//line parser/classad.y:155 { yyVAL.expr = &ast.BinaryOp{Op: "is", Left: yyDollar[1].expr, Right: yyDollar[3].expr} } - case 28: + case 29: yyDollar = yyS[yypt-3 : yypt+1] -//line parser/classad.y:151 +//line parser/classad.y:157 { yyVAL.expr = &ast.BinaryOp{Op: "isnt", Left: yyDollar[1].expr, Right: yyDollar[3].expr} } - case 29: + case 30: yyDollar = yyS[yypt-1 : yypt+1] -//line parser/classad.y:156 +//line parser/classad.y:162 { yyVAL.expr = yyDollar[1].expr } - case 30: + case 31: yyDollar = yyS[yypt-3 : yypt+1] -//line parser/classad.y:158 +//line parser/classad.y:164 { yyVAL.expr = &ast.BinaryOp{Op: "<", Left: yyDollar[1].expr, Right: yyDollar[3].expr} } - case 31: + case 32: yyDollar = yyS[yypt-3 : yypt+1] -//line parser/classad.y:160 +//line parser/classad.y:166 { yyVAL.expr = &ast.BinaryOp{Op: ">", Left: yyDollar[1].expr, Right: yyDollar[3].expr} } - case 32: + case 33: yyDollar = yyS[yypt-3 : yypt+1] -//line parser/classad.y:162 +//line parser/classad.y:168 { yyVAL.expr = &ast.BinaryOp{Op: "<=", Left: yyDollar[1].expr, Right: yyDollar[3].expr} } - case 33: + case 34: yyDollar = yyS[yypt-3 : yypt+1] -//line parser/classad.y:164 +//line parser/classad.y:170 { yyVAL.expr = &ast.BinaryOp{Op: ">=", Left: yyDollar[1].expr, Right: yyDollar[3].expr} } - case 34: + case 35: yyDollar = yyS[yypt-1 : yypt+1] -//line parser/classad.y:169 +//line parser/classad.y:175 { yyVAL.expr = yyDollar[1].expr } - case 35: + case 36: yyDollar = yyS[yypt-3 : yypt+1] -//line parser/classad.y:171 +//line parser/classad.y:177 { yyVAL.expr = &ast.BinaryOp{Op: "<<", Left: yyDollar[1].expr, Right: yyDollar[3].expr} } - case 36: + case 37: yyDollar = yyS[yypt-3 : yypt+1] -//line parser/classad.y:173 +//line parser/classad.y:179 { yyVAL.expr = &ast.BinaryOp{Op: ">>", Left: yyDollar[1].expr, Right: yyDollar[3].expr} } - case 37: + case 38: yyDollar = yyS[yypt-3 : yypt+1] -//line parser/classad.y:175 +//line parser/classad.y:181 { yyVAL.expr = &ast.BinaryOp{Op: ">>>", Left: yyDollar[1].expr, Right: yyDollar[3].expr} } - case 38: + case 39: yyDollar = yyS[yypt-1 : yypt+1] -//line parser/classad.y:180 +//line parser/classad.y:186 { yyVAL.expr = yyDollar[1].expr } - case 39: + case 40: yyDollar = yyS[yypt-3 : yypt+1] -//line parser/classad.y:182 +//line parser/classad.y:188 { yyVAL.expr = &ast.BinaryOp{Op: "+", Left: yyDollar[1].expr, Right: yyDollar[3].expr} } - case 40: + case 41: yyDollar = yyS[yypt-3 : yypt+1] -//line parser/classad.y:184 +//line parser/classad.y:190 { yyVAL.expr = &ast.BinaryOp{Op: "-", Left: yyDollar[1].expr, Right: yyDollar[3].expr} } - case 41: + case 42: yyDollar = yyS[yypt-1 : yypt+1] -//line parser/classad.y:189 +//line parser/classad.y:195 { yyVAL.expr = yyDollar[1].expr } - case 42: + case 43: yyDollar = yyS[yypt-3 : yypt+1] -//line parser/classad.y:191 +//line parser/classad.y:197 { yyVAL.expr = &ast.BinaryOp{Op: "*", Left: yyDollar[1].expr, Right: yyDollar[3].expr} } - case 43: + case 44: yyDollar = yyS[yypt-3 : yypt+1] -//line parser/classad.y:193 +//line parser/classad.y:199 { yyVAL.expr = &ast.BinaryOp{Op: "/", Left: yyDollar[1].expr, Right: yyDollar[3].expr} } - case 44: + case 45: yyDollar = yyS[yypt-3 : yypt+1] -//line parser/classad.y:195 +//line parser/classad.y:201 { yyVAL.expr = &ast.BinaryOp{Op: "%", Left: yyDollar[1].expr, Right: yyDollar[3].expr} } - case 45: + case 46: yyDollar = yyS[yypt-1 : yypt+1] -//line parser/classad.y:200 +//line parser/classad.y:206 { yyVAL.expr = yyDollar[1].expr } - case 46: + case 47: yyDollar = yyS[yypt-2 : yypt+1] -//line parser/classad.y:202 +//line parser/classad.y:208 { yyVAL.expr = &ast.UnaryOp{Op: "-", Expr: yyDollar[2].expr} } - case 47: + case 48: yyDollar = yyS[yypt-2 : yypt+1] -//line parser/classad.y:204 +//line parser/classad.y:210 { yyVAL.expr = &ast.UnaryOp{Op: "+", Expr: yyDollar[2].expr} } - case 48: + case 49: yyDollar = yyS[yypt-2 : yypt+1] -//line parser/classad.y:206 +//line parser/classad.y:212 { yyVAL.expr = &ast.UnaryOp{Op: "!", Expr: yyDollar[2].expr} } - case 49: + case 50: yyDollar = yyS[yypt-2 : yypt+1] -//line parser/classad.y:208 +//line parser/classad.y:214 { yyVAL.expr = &ast.UnaryOp{Op: "~", Expr: yyDollar[2].expr} } - case 50: + case 51: yyDollar = yyS[yypt-1 : yypt+1] -//line parser/classad.y:213 +//line parser/classad.y:219 { yyVAL.expr = yyDollar[1].expr } - case 51: + case 52: yyDollar = yyS[yypt-3 : yypt+1] -//line parser/classad.y:215 +//line parser/classad.y:221 { yyVAL.expr = &ast.SelectExpr{Record: yyDollar[1].expr, Attr: yyDollar[3].str} } - case 52: + case 53: yyDollar = yyS[yypt-4 : yypt+1] -//line parser/classad.y:217 +//line parser/classad.y:223 { yyVAL.expr = &ast.SubscriptExpr{Container: yyDollar[1].expr, Index: yyDollar[3].expr} } - case 53: + case 54: yyDollar = yyS[yypt-4 : yypt+1] -//line parser/classad.y:219 +//line parser/classad.y:225 { yyVAL.expr = &ast.FunctionCall{Name: yyDollar[1].str, Args: yyDollar[3].exprlist} } - case 54: + case 55: yyDollar = yyS[yypt-1 : yypt+1] -//line parser/classad.y:224 +//line parser/classad.y:230 { yyVAL.expr = yyDollar[1].expr } - case 55: + case 56: yyDollar = yyS[yypt-1 : yypt+1] -//line parser/classad.y:226 +//line parser/classad.y:232 { name, scope := ParseScopedIdentifier(yyDollar[1].str) yyVAL.expr = &ast.AttributeReference{Name: name, Scope: scope} } - case 56: + case 57: yyDollar = yyS[yypt-3 : yypt+1] -//line parser/classad.y:231 +//line parser/classad.y:237 { yyVAL.expr = yyDollar[2].expr } - case 57: + case 58: yyDollar = yyS[yypt-3 : yypt+1] -//line parser/classad.y:233 +//line parser/classad.y:239 { yyVAL.expr = &ast.ListLiteral{Elements: yyDollar[2].exprlist} } - case 58: + case 59: yyDollar = yyS[yypt-1 : yypt+1] -//line parser/classad.y:235 +//line parser/classad.y:241 { yyVAL.expr = &ast.RecordLiteral{ClassAd: yyDollar[1].classad} } - case 59: + case 60: yyDollar = yyS[yypt-1 : yypt+1] -//line parser/classad.y:240 +//line parser/classad.y:246 { yyVAL.expr = &ast.IntegerLiteral{Value: yyDollar[1].integer} } - case 60: + case 61: yyDollar = yyS[yypt-1 : yypt+1] -//line parser/classad.y:242 +//line parser/classad.y:248 { yyVAL.expr = &ast.RealLiteral{Value: yyDollar[1].real} } - case 61: + case 62: yyDollar = yyS[yypt-1 : yypt+1] -//line parser/classad.y:244 +//line parser/classad.y:250 { yyVAL.expr = &ast.StringLiteral{Value: yyDollar[1].str} } - case 62: + case 63: yyDollar = yyS[yypt-1 : yypt+1] -//line parser/classad.y:246 +//line parser/classad.y:252 { yyVAL.expr = &ast.BooleanLiteral{Value: yyDollar[1].boolean} } - case 63: + case 64: yyDollar = yyS[yypt-1 : yypt+1] -//line parser/classad.y:248 +//line parser/classad.y:254 { yyVAL.expr = &ast.UndefinedLiteral{} } - case 64: + case 65: yyDollar = yyS[yypt-1 : yypt+1] -//line parser/classad.y:250 +//line parser/classad.y:256 { yyVAL.expr = &ast.ErrorLiteral{} } - case 65: + case 66: yyDollar = yyS[yypt-0 : yypt+1] -//line parser/classad.y:255 +//line parser/classad.y:261 { yyVAL.exprlist = []ast.Expr{} } - case 66: + case 67: yyDollar = yyS[yypt-1 : yypt+1] -//line parser/classad.y:257 +//line parser/classad.y:263 { yyVAL.exprlist = yyDollar[1].exprlist } - case 67: + case 68: yyDollar = yyS[yypt-1 : yypt+1] -//line parser/classad.y:262 +//line parser/classad.y:268 { yyVAL.exprlist = []ast.Expr{yyDollar[1].expr} } - case 68: + case 69: yyDollar = yyS[yypt-3 : yypt+1] -//line parser/classad.y:264 +//line parser/classad.y:270 { yyVAL.exprlist = append(yyDollar[1].exprlist, yyDollar[3].expr) }