feat: elf parser (#21) #30
							
								
								
									
										9
									
								
								internal/parsers/elf/meta.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								internal/parsers/elf/meta.go
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,9 @@
 | 
				
			||||||
 | 
					package elf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var name = "elf"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						stage.RegisterParser(name, &Elf{})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										41
									
								
								internal/parsers/elf/model.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								internal/parsers/elf/model.go
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,41 @@
 | 
				
			||||||
 | 
					package elf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Toplevel struct {
 | 
				
			||||||
 | 
						Title   string   `json:"title"`
 | 
				
			||||||
 | 
						Modules []Module `json:"modules"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Module struct {
 | 
				
			||||||
 | 
						Entries   []Entry `json:"entries"`
 | 
				
			||||||
 | 
						DebugInfo string  `json:"debug_info"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Entry []any
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Report struct {
 | 
				
			||||||
 | 
						File  string `json:"file"`
 | 
				
			||||||
 | 
						Name  string `json:"name"`
 | 
				
			||||||
 | 
						Cases []Case `json:"cases" mapstructure:"cases"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Case struct {
 | 
				
			||||||
 | 
						Binders        []Binder `mapstructure:"binders"`
 | 
				
			||||||
 | 
						Context        *string  `mapstructure:"context"`
 | 
				
			||||||
 | 
						Depths         *int     `mapstructure:"depths"`
 | 
				
			||||||
 | 
						Code           *string  `mapstructure:"code"`
 | 
				
			||||||
 | 
						Plain          *int     `mapstructure:"plain"`
 | 
				
			||||||
 | 
						Weighed        *float64 `mapstructure:"weighed"`
 | 
				
			||||||
 | 
						Detail         *string  `mapstructure:"detail"`
 | 
				
			||||||
 | 
						SimilarityRate float64  `mapstructure:"similarity_rate"`
 | 
				
			||||||
 | 
						Sources        []Source `mapstructure:"srcs"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Binder struct {
 | 
				
			||||||
 | 
						Binder string `json:"binder"`
 | 
				
			||||||
 | 
						Pos    string `json:"pos"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Source struct {
 | 
				
			||||||
 | 
						Context string `json:"context"`
 | 
				
			||||||
 | 
						Code    string `json:"code"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										96
									
								
								internal/parsers/elf/parser.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								internal/parsers/elf/parser.go
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,96 @@
 | 
				
			||||||
 | 
					package elf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"log/slog"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage"
 | 
				
			||||||
 | 
						"github.com/criyle/go-judge/envexec"
 | 
				
			||||||
 | 
						"github.com/mitchellh/mapstructure"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Conf struct {
 | 
				
			||||||
 | 
						Score   int
 | 
				
			||||||
 | 
						Comment string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Elf struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func Parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult {
 | 
				
			||||||
 | 
						stdout := executorResult.Files["stdout"]
 | 
				
			||||||
 | 
						stderr := executorResult.Files["stderr"]
 | 
				
			||||||
 | 
						if executorResult.Status != stage.Status(envexec.StatusAccepted) {
 | 
				
			||||||
 | 
							return stage.ParserResult{
 | 
				
			||||||
 | 
								Score: 0,
 | 
				
			||||||
 | 
								Comment: fmt.Sprintf(
 | 
				
			||||||
 | 
									"Unexpected executor status: %s.\nStderr: %s",
 | 
				
			||||||
 | 
									executorResult.Status, stderr,
 | 
				
			||||||
 | 
								),
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var topLevel Toplevel
 | 
				
			||||||
 | 
						err := json.Unmarshal([]byte(stdout), &topLevel)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return stage.ParserResult{
 | 
				
			||||||
 | 
								Score:   0,
 | 
				
			||||||
 | 
								Comment: fmt.Sprintf("Failed to parse result: %s", err),
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, module := range topLevel.Modules {
 | 
				
			||||||
 | 
							for _, entry := range module.Entries {
 | 
				
			||||||
 | 
								kind := entry[0].(string)
 | 
				
			||||||
 | 
								report := Report{}
 | 
				
			||||||
 | 
								err := mapstructure.Decode(entry[1], &report)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									slog.Error("elf parse", "mapstructure decode err", err)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								slog.Debug("elf parse", "report file", report.File)
 | 
				
			||||||
 | 
								slog.Debug("elf parse", "report name", report.Name)
 | 
				
			||||||
 | 
								slog.Debug("elf parse", "report kind", kind)
 | 
				
			||||||
 | 
								for _, caseObj := range report.Cases {
 | 
				
			||||||
 | 
									switch kind {
 | 
				
			||||||
 | 
									case "ParenDep":
 | 
				
			||||||
 | 
										slog.Debug("elf parse", "binders", caseObj.Binders)
 | 
				
			||||||
 | 
										slog.Debug("elf parse", "context", caseObj.Context)
 | 
				
			||||||
 | 
										slog.Debug("elf parse", "depths", caseObj.Depths)
 | 
				
			||||||
 | 
										slog.Debug("elf parse", "code", caseObj.Code)
 | 
				
			||||||
 | 
									case "CodeLen":
 | 
				
			||||||
 | 
										slog.Debug("elf parse", "binders", caseObj.Binders)
 | 
				
			||||||
 | 
										slog.Debug("elf parse", "context", caseObj.Context)
 | 
				
			||||||
 | 
										slog.Debug("elf parse", "plain", caseObj.Plain)
 | 
				
			||||||
 | 
										slog.Debug("elf parse", "weighed", caseObj.Weighed)
 | 
				
			||||||
 | 
										slog.Debug("elf parse", "code", caseObj.Code)
 | 
				
			||||||
 | 
									case "OverArity":
 | 
				
			||||||
 | 
										slog.Debug("elf parse", "binders", caseObj.Binders)
 | 
				
			||||||
 | 
										slog.Debug("elf parse", "context", caseObj.Context)
 | 
				
			||||||
 | 
										slog.Debug("elf parse", "detail", caseObj.Detail)
 | 
				
			||||||
 | 
										slog.Debug("elf parse", "code", caseObj.Code)
 | 
				
			||||||
 | 
									case "CodeDup":
 | 
				
			||||||
 | 
										slog.Debug("elf parse", "similarity rate", caseObj.SimilarityRate)
 | 
				
			||||||
 | 
										for _, source := range caseObj.Sources {
 | 
				
			||||||
 | 
											slog.Debug("elf parse", "context", source.Context, "code", source.Code)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return stage.ParserResult{
 | 
				
			||||||
 | 
							Score:   conf.Score,
 | 
				
			||||||
 | 
							Comment: conf.Comment,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (*Elf) Run(results []stage.ExecutorResult, confAny any) (
 | 
				
			||||||
 | 
						[]stage.ParserResult, bool, error,
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
						conf, err := stage.DecodeConf[Conf](confAny)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, true, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var res []stage.ParserResult
 | 
				
			||||||
 | 
						for _, result := range results {
 | 
				
			||||||
 | 
							res = append(res, Parse(result, *conf))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return res, false, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user