From e7df875d245ef964ae199a25511e66fbd27a6837 Mon Sep 17 00:00:00 2001 From: Boming Zhang Date: Sat, 8 Jun 2024 20:43:46 -0400 Subject: [PATCH] feat: elf parser only parse json output to struct --- internal/parsers/elf/meta.go | 9 ++++ internal/parsers/elf/model.go | 41 +++++++++++++++ internal/parsers/elf/parser.go | 96 ++++++++++++++++++++++++++++++++++ 3 files changed, 146 insertions(+) create mode 100644 internal/parsers/elf/meta.go create mode 100644 internal/parsers/elf/model.go create mode 100644 internal/parsers/elf/parser.go diff --git a/internal/parsers/elf/meta.go b/internal/parsers/elf/meta.go new file mode 100644 index 0000000..0557a3c --- /dev/null +++ b/internal/parsers/elf/meta.go @@ -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{}) +} diff --git a/internal/parsers/elf/model.go b/internal/parsers/elf/model.go new file mode 100644 index 0000000..a8e7960 --- /dev/null +++ b/internal/parsers/elf/model.go @@ -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"` +} diff --git a/internal/parsers/elf/parser.go b/internal/parsers/elf/parser.go new file mode 100644 index 0000000..96e4abd --- /dev/null +++ b/internal/parsers/elf/parser.go @@ -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 +}