mirror of
https://github.com/crawlab-team/crawlab.git
synced 2026-01-21 17:21:09 +01:00
feat: added modules
This commit is contained in:
208
template-parser/general_parser.go
Normal file
208
template-parser/general_parser.go
Normal file
@@ -0,0 +1,208 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/robertkrimen/otto"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type GeneralParser struct {
|
||||
tagPattern string
|
||||
tagRegexp *regexp.Regexp
|
||||
mathPattern string
|
||||
mathRegexp *regexp.Regexp
|
||||
template string
|
||||
indexes [][]int
|
||||
matches [][]string
|
||||
placeholders []string
|
||||
variables []Variable
|
||||
vm *otto.Otto
|
||||
}
|
||||
|
||||
const VariableNameResult = "result"
|
||||
const ValueNameNA = "N/A"
|
||||
|
||||
func (p *GeneralParser) Parse(template string) (err error) {
|
||||
p.template = template
|
||||
p.indexes = p.tagRegexp.FindAllStringIndex(template, -1)
|
||||
p.matches = p.tagRegexp.FindAllStringSubmatch(template, -1)
|
||||
for _, arr := range p.matches {
|
||||
p.placeholders = append(p.placeholders, arr[1])
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *GeneralParser) Render(args ...interface{}) (content string, err error) {
|
||||
// render tag content
|
||||
content, err = p.renderTagContent(args...)
|
||||
if err != nil {
|
||||
return content, err
|
||||
}
|
||||
|
||||
// render math content
|
||||
content, err = p.renderMathContent(content)
|
||||
if err != nil {
|
||||
return content, err
|
||||
}
|
||||
|
||||
return content, nil
|
||||
}
|
||||
|
||||
func (p *GeneralParser) renderTagContent(args ...interface{}) (content string, err error) {
|
||||
// validate
|
||||
if len(args) == 0 {
|
||||
return "", errors.New("no arguments")
|
||||
}
|
||||
|
||||
// first argument
|
||||
arg := args[0]
|
||||
|
||||
// content
|
||||
content = p.template
|
||||
|
||||
// old strings
|
||||
var oldStrList []string
|
||||
for _, index := range p.indexes {
|
||||
// old string
|
||||
oldStr := content[index[0]:index[1]]
|
||||
oldStrList = append(oldStrList, oldStr)
|
||||
}
|
||||
|
||||
// iterate placeholders
|
||||
for i, placeholder := range p.placeholders {
|
||||
// variable
|
||||
v, err := NewVariable(arg, placeholder)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// value
|
||||
value, err := v.GetValue()
|
||||
if err != nil || value == nil {
|
||||
value = ValueNameNA
|
||||
}
|
||||
|
||||
// old string
|
||||
oldStr := oldStrList[i]
|
||||
|
||||
// new string
|
||||
var newStr string
|
||||
switch value.(type) {
|
||||
case string:
|
||||
newStr = value.(string)
|
||||
default:
|
||||
newStrBytes, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
newStr = string(newStrBytes)
|
||||
}
|
||||
|
||||
// replace old string with new string
|
||||
content = strings.Replace(content, oldStr, newStr, 1)
|
||||
}
|
||||
|
||||
return content, nil
|
||||
}
|
||||
|
||||
func (p *GeneralParser) renderMathContent(inputContent string) (content string, err error) {
|
||||
content = inputContent
|
||||
indexes := p.mathRegexp.FindAllStringIndex(inputContent, -1)
|
||||
matches := p.mathRegexp.FindAllStringSubmatch(inputContent, -1)
|
||||
|
||||
// old strings
|
||||
var oldStrList []string
|
||||
for _, index := range indexes {
|
||||
// old string
|
||||
oldStr := content[index[0]:index[1]]
|
||||
oldStrList = append(oldStrList, oldStr)
|
||||
}
|
||||
|
||||
// iterate matches
|
||||
for i, m := range matches {
|
||||
// js script to run to get evaluate result
|
||||
script := fmt.Sprintf("%s = %s; %s", VariableNameResult, m[1], VariableNameResult)
|
||||
|
||||
// replace NA
|
||||
script = strings.ReplaceAll(script, ValueNameNA, "NaN")
|
||||
|
||||
// value
|
||||
value, err := p.vm.Run(script)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// old string
|
||||
oldStr := oldStrList[i]
|
||||
|
||||
// new string
|
||||
newStr := value.String()
|
||||
|
||||
// replace old string with new string
|
||||
content = strings.Replace(content, oldStr, newStr, 1)
|
||||
}
|
||||
|
||||
return content, nil
|
||||
}
|
||||
|
||||
func (p *GeneralParser) GetPlaceholders() (placeholders []string) {
|
||||
return p.placeholders
|
||||
}
|
||||
|
||||
func NewGeneralParser() (p Parser, err error) {
|
||||
// tag regexp
|
||||
tagPrefix := "\\{\\{"
|
||||
tagSuffix := "\\}\\}"
|
||||
tagBasicChars := "\\$\\.\\w_"
|
||||
tagAssociateChars := "\\[\\]:"
|
||||
tagPattern := fmt.Sprintf(
|
||||
"%s *([%s%s]+) *%s",
|
||||
tagPrefix,
|
||||
tagBasicChars,
|
||||
tagAssociateChars,
|
||||
tagSuffix,
|
||||
)
|
||||
tagRegexp, err := regexp.Compile(tagPattern)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// math regexp
|
||||
mathPrefix := "\\{#"
|
||||
mathSuffix := "#\\}"
|
||||
mathBasicChars := " \\(\\)"
|
||||
mathOpChars := "\\+\\-\\*/%"
|
||||
mathNumChars := "\\d\\."
|
||||
mathSpecialChars := "(?:NaN|null)"
|
||||
mathPattern := fmt.Sprintf(
|
||||
"%s *([%s%s%s%s]+) *%s",
|
||||
mathPrefix,
|
||||
mathBasicChars,
|
||||
mathOpChars,
|
||||
mathNumChars,
|
||||
mathSpecialChars,
|
||||
mathSuffix,
|
||||
)
|
||||
mathRegexp, err := regexp.Compile(mathPattern)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// math vm
|
||||
vm := otto.New()
|
||||
|
||||
// parser
|
||||
p = &GeneralParser{
|
||||
tagPattern: tagPattern,
|
||||
tagRegexp: tagRegexp,
|
||||
mathPattern: mathPattern,
|
||||
mathRegexp: mathRegexp,
|
||||
vm: vm,
|
||||
}
|
||||
|
||||
return p, nil
|
||||
}
|
||||
Reference in New Issue
Block a user