Commit 3ff6fd3a authored by mohamad.alturky's avatar mohamad.alturky

adding source

parent c5750c9d
package FileManagement
import (
"bufio"
"log"
"os"
)
/**
* reads file data and returns it as a string
*/
func ReadData(fileName string) string {
file, err := os.Open(fileName)
if err != nil {
log.Fatal(err)
}
defer file.Close()
data := ""
scanner := bufio.NewScanner(file)
for scanner.Scan() {
data = data + scanner.Text() + "\n"
}
return data
}
/**
* writes text data to a file
*/
func WriteFile(filePath string, text string) {
f, err := os.Create(filePath)
if err != nil {
log.Fatal(err)
}
defer f.Close()
_, err = f.WriteString(text)
if err != nil {
log.Fatal(err)
}
}
module donut
go 1.22.0
require github.com/TwiN/go-color v1.4.1
github.com/TwiN/go-color v1.4.1 h1:mqG0P/KBgHKVqmtL5ye7K0/Gr4l6hTksPgTgMk3mUzc=
github.com/TwiN/go-color v1.4.1/go.mod h1:WcPf/jtiW95WBIsEeY1Lc/b8aaWoiqQpu5cf8WFxu+s=
package Languages
import (
Types "donut/types"
)
type Bridge struct {
TemplateCodeHandler Types.TextToTextConverter
InjectCodeHandler Types.TextToTextConverter
MainFunctionHandler Types.TextAppendUtil
ImportsHandler Types.TextAppendUtil
}
package main
import (
Tokenizer "donut/tokenization"
"github.com/TwiN/go-color"
)
func main() {
template := `
@template
{{
text
@exec
{{
code
@template
{{
text
}}
code
}}
text
@exec
{{ 11111111
code
@template
{{
text
}}
code
}}
}}
`
new := ""
startingIdx := 0
for {
if startingIdx == len(template) {
break
}
res := Tokenizer.ConvertNestingToConcatenation(startingIdx, template, "exec", "template")
startingIdx = res.TerminatedAt
new = new + res.Template
}
// println("------------------")
// println(template2.Template)
// println("------------------")
// println(template2.TerminatedAt)
// println("------------------")
// println(len(template))
println(color.Colorize(color.Blue, `
|‾‾‾‾‾‾‾‾\ |‾‾‾‾‾‾‾‾‾| |‾‾‾‾‾\ |‾‾| |‾‾| |‾‾| |‾‾‾‾‾‾‾‾‾‾‾‾|
| |‾‾‾\ \ | |‾‾‾| | | |\ \ | | | | | | ‾‾‾‾| |‾‾‾‾
| | | | | | | | | | \ \| | | | | | | |
| |___/ / | |___| | | | \ | | |___| | | |
|________/ |_________| |__| \____| |_________| |__|
`))
println(new)
// println(color.Colorize(color.Red, "This is also red"))
}
// package main
// // A simple program demonstrating the paginator component from the Bubbles
// // component library.
// import (
// "fmt"
// "log"
// "strings"
// "github.com/charmbracelet/bubbles/paginator"
// "github.com/charmbracelet/lipgloss"
// tea "github.com/charmbracelet/bubbletea"
// )
// func newModel() model {
// var items []string
// for i := 1; i < 101; i++ {
// text := fmt.Sprintf("Item %d", i)
// items = append(items, text)
// }
// p := paginator.New()
// p.Type = paginator.Dots
// p.PerPage = 10
// p.ActiveDot = lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "235", Dark: "252"}).Render("•")
// p.InactiveDot = lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "250", Dark: "238"}).Render("•")
// p.SetTotalPages(len(items))
// return model{
// paginator: p,
// items: items,
// }
// }
// type model struct {
// items []string
// paginator paginator.Model
// }
// func (m model) Init() tea.Cmd {
// return nil
// }
// func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
// var cmd tea.Cmd
// switch msg := msg.(type) {
// case tea.KeyMsg:
// switch msg.String() {
// case "q", "esc", "ctrl+c":
// return m, tea.Quit
// }
// }
// m.paginator, cmd = m.paginator.Update(msg)
// return m, cmd
// }
// func (m model) View() string {
// var b strings.Builder
// b.WriteString("\n Paginator Example\n\n")
// start, end := m.paginator.GetSliceBounds(len(m.items))
// for _, item := range m.items[start:end] {
// b.WriteString(" • " + item + "\n\n")
// }
// b.WriteString(" " + m.paginator.View())
// b.WriteString("\n\n h/l ←/→ page • q: quit\n")
// return b.String()
// }
// func main() {
// p := tea.NewProgram(newModel())
// if _, err := p.Run(); err != nil {
// log.Fatal(err)
// }
// }
package Settings
const IMPORT_KEY_WORD = "@import"
const DEFINE_KEY_WORD = "@define"
const EXECUTE_KEY_WORD = "@exec"
const TEMPLATE_KEY_WORD = "@template"
const FINAL_GENERATED_CODE_CONTAINER = "CODE_CONTAINER"
package Tokenizer
import (
Types "donut/types"
"regexp"
)
/*
*
- gets a template then extract the content of the directive
- and mutaute it to remove the content of it.
*/
func ExtractDirectiveContent(template string, directiveName string) [2]string {
/**
* regex to find the directive keyword, it will return list of matches
* the match is stuctured like this [starting_index,end_index]
*/
re := regexp.MustCompile(directiveName)
/**
* the places where the directive keyword found
*/
directiveMatches := re.FindAllStringIndex(template, -1)
/**
* the index that we will use to loop over the template
*/
loopIndex := 0
/**
* the index of where the start `{{` found
*/
indexOfOpenedBracket := 0
/**
* the index of where the start `}}` found
*/
directiveFinishedFrom := 0
/**
* loop over the template from the index where we found
* the directive keyword until we find the `}}`
*/
for loopIndex = directiveMatches[0][0]; loopIndex < len(template); loopIndex++ {
/**
* find `{{` and same its index
*/
if template[loopIndex] == '{' && template[loopIndex+1] == '{' {
indexOfOpenedBracket = loopIndex
}
/**
* break the loop because we found the temination token
*/
if template[loopIndex] == '}' && template[loopIndex+1] == '}' {
break
}
}
/**
* the directive content that will be returned from the function
*/
directiveContent := template[indexOfOpenedBracket+2 : loopIndex]
/**
* the index where we finished the parsing of the directive content
*/
directiveFinishedFrom = loopIndex + 2
/**
* mutate the template to return the old template but cleaned from the directive content
*/
newTemplate := template[:directiveMatches[0][0]] + template[directiveFinishedFrom:]
return [2]string{directiveContent, newTemplate}
}
/*
*
- gets a template then extract the content of the directive
- and returns the index where it ended
*/
func GetDirectiveContentWithTerminationIndex(template string, directiveName string) Types.DirectiveContentSpecification {
/**
* regex to find the directive keyword, it will return list of matches
* the match is stuctured like this [starting_index,end_index]
*/
re := regexp.MustCompile(directiveName)
/**
* the places where the directive keyword found
*/
directiveMatches := re.FindAllStringIndex(template, -1)
/**
* the index that we will use to loop over the template
*/
loopIndex := 0
/**
* the index of where the start `{{` found
*/
indexOfOpenedBracket := 0
/**
* loop over the template from the index where we found
* the directive keyword until we find the `}}`
*/
for loopIndex = directiveMatches[0][0]; loopIndex < len(template); loopIndex++ {
/**
* find `{{` and same its index
*/
if template[loopIndex] == '{' && template[loopIndex+1] == '{' {
indexOfOpenedBracket = loopIndex
}
/**
* break the loop because we found the temination token
*/
if template[loopIndex] == '}' && template[loopIndex+1] == '}' {
break
}
}
/**
* the directive content that will be returned from the function
*/
directiveContent := template[indexOfOpenedBracket+2 : loopIndex]
/**
* the index where we finished the parsing of the directive content
*/
directiveFinishedFrom := loopIndex + 2
return Types.DirectiveContentSpecification{directiveContent, directiveFinishedFrom}
}
func FindTerminationIndex(template string, startingIndex int) int {
counter := 0
passed := false
k := startingIndex
indexOfClosing := k
for ; k < len(template); k++ {
if counter == 0 && passed {
indexOfClosing = k + 1
break
}
if template[k] == '}' && template[k+1] == '}' {
passed = true
counter = counter - 1
}
if template[k] == '{' && template[k+1] == '{' {
passed = true
counter = counter + 1
}
}
return indexOfClosing
}
package Tokenizer
import (
Types "donut/types"
"regexp"
)
/*
*
- gets a template then replace all occurences of it with the fn(its content)
fn is the transformation that we want to apply to the content of the template
- returns the updated template
*/
func ReplaceDirectiveContent(template string, directiveName string, fn Types.TextToTextConverter) string {
/**
* regex to find the directive keyword, it will return list of matches
* the match is stuctured like this [starting_index,end_index]
*/
re := regexp.MustCompile(directiveName)
/**
* the places where the directive keyword found
*/
directiveMatches := re.FindAllStringIndex(template, -1)
/**
* pair of values
* the first is the content of the directive
* the second is the index where the directive is terminated
*/
var directivesContentSpecification = []Types.DirectiveContentSpecification{}
/**
* loop over the occurences of the directive
* gets the directive content specification
*/
for _, tuple := range directiveMatches {
dc := GetDirectiveContentWithTerminationIndex(template[tuple[0]:], directiveName)
directivesContentSpecification = append(directivesContentSpecification, dc)
}
/**
* the new template will contain the old one but
* we will replace all occurences of the directive with its content
* with the function fn
*/
newTemplate := ""
/**
* index to add to the new template the old value from this index
* to the start of the directive, so that we can accumulate the new template
*/
leftIndex := 0
/**
* loop over the occurences of the directive
* and construct the new template
*/
for index, tuple := range directiveMatches {
// adding the content before the directive
newTemplate = newTemplate + template[leftIndex:tuple[0]]
// adding the transformed content of the directive
newTemplate = newTemplate + fn(directivesContentSpecification[index].Content)
// update the leftIndex it will be equal to the index where the directive closed
leftIndex = directivesContentSpecification[index].TerminationIndex + tuple[0]
}
// adding the remaining template which will be the same of the old because there isn't any directive occurence in it
newTemplate = newTemplate + template[leftIndex:]
return newTemplate
}
package Tokenizer
import (
Types "donut/types"
)
func ConvertNestingToConcatenation(startAt int, template string, executeToken string, templateToken string) Types.RecursionResult {
/*
* the answer is the string where we will save the mutated template
*/
answer := ""
/*
* the termination index will contain the index where the prosses terminated
*/
terminationIndex := len(template)
/*
* loop over the template from the parameter @startingIndex
* the end of the scope which is where the nesting scope end
*/
for index := startAt; index < len(template); {
/*
* adding the characher to the template
*/
answer = answer + string(template[index])
/**
* increment the index because we handle this charachter
*/
index++
/**
* start handling the nesting
*/
if template[index-1] == '@' {
/**
* case of templateToken scope
*/
if template[index:index+len(templateToken)] == templateToken {
/**
* adding the templateToken after the @ so that the template will not change
*/
answer = answer + templateToken
/**
* jump to the index after the templateToken
*/
index = index + len(templateToken)
/**
* the index where the templateToken scope end
*/
terminationIndex = FindTerminationIndex(template, index)
/**
* start proccessing the inner scope
*/
for idx := index; idx < terminationIndex; {
/**
* if we found a nested scope we will recursively handle it
*/
if template[idx] == '@' {
/**
* get the result of the recursive function
*/
next := ConvertNestingToConcatenation(idx, template, executeToken, templateToken)
/**
* jump to the terminated index of the inner nested block
*/
idx = next.TerminatedAt
/**
* update the answer to concate the result of the inner nested block
*/
answer = answer + "}" + "}" + next.Template + "@" + templateToken + "{" + "{"
} else {
/**
* add the character directly because the is no nesting
*/
answer = answer + string(template[idx])
/**
* increament the loop index
*/
idx++
}
}
/**
* terminate the process
*/
index = terminationIndex
break
}
/**
* case of executeToken scope
*/
if template[index:index+len(executeToken)] == executeToken {
/**
* adding the executeToken after the @ so that the template will not change
*/
answer = answer + executeToken
/**
* jump to the index after the executeToken
*/
index = index + len(executeToken)
/**
* the index where the executeToken scope end
*/
terminationIndex = FindTerminationIndex(template, index)
/**
* start proccessing the inner scope
*/
for idx := index; idx < terminationIndex; {
/**
* if we found a nested scope we will recursively handle it
*/
if template[idx] == '@' {
/**
* get the result of the recursive function
*/
next := ConvertNestingToConcatenation(idx, template, executeToken, templateToken)
/**
* jump to the terminated index of the inner nested block
*/
idx = next.TerminatedAt
/**
* update the answer to concate the result of the inner nested block
*/
answer = answer + "}" + "}" + next.Template + "@" + executeToken + "{" + "{"
} else {
/**
* add the character directly because the is no nesting
*/
answer = answer + string(template[idx])
/**
* increament the loop index
*/
idx++
}
}
/**
* terminate the process
*/
index = terminationIndex
break
}
}
}
return Types.RecursionResult{answer, terminationIndex}
}
package Types
/*
*
- contains the content of the directive
ex. the directive will be like this
@directive {{ content }}
- the termination index that the }} appeared
ex. if the the index = 6 of the first } in this termination token "}}"
the TerminationIndex = 8 the next index that is'nt }
*/
type DirectiveContentSpecification struct {
Content string
TerminationIndex int
}
package Types
/*
* RecursionResult is the container for the output of the function ConvertNestingToConcatenation
- it will return the converted template
- and the index where the function finished its proccess
*/
type RecursionResult struct {
Template string
TerminatedAt int
}
package Types
/*
*
- type of functions gets two texts and convert them and make them in a desirable order
*/
type TextAppendUtil func(string, string) string
package Types
/*
*
- type of functions gets string and return another one
*/
type TextToTextConverter func(string) string
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment