diff --git a/src/compiler/compiler.go b/src/compiler/compiler.go index d3c92d6..d7e52bc 100644 --- a/src/compiler/compiler.go +++ b/src/compiler/compiler.go @@ -7,216 +7,6 @@ import ( "strings" ) -type Question interface {} - -type SingleAnswerQuestion struct { - id string; - question string; - answer string; - section string; -} - -type Choice struct { - answer string; - isCorrect bool; -} - -type MultipleChoiceQuestion struct { - id string; - question string; - choices []Choice; - section string; -} - -type QuestionElement struct { - isDash bool; - content string; -} - -var automata map[TokenType][]TokenType - -type CompilerErr struct { - message string; - row int32; - column int32; -} - -func (e CompilerErr) Error() string { - return fmt.Sprintf("%d:%d - %s", e.row, e.column, e.message) -} - -func contains(s []TokenType, e TokenType) bool { - for _, a := range s { - if a == e { - return true - } - } - return false -} - -func parserAutomata() map[TokenType][]TokenType { - automata := make(map[TokenType][]TokenType) - automata[TextFragment] = []TokenType{ - QuestionEnd, ElementDashStart, ElementPlusStart, SectionIdentifierStart, SectionStart, EOF, SectionEnd, - } - automata[QuestionEnd] = []TokenType{ - ElementDashStart, ElementPlusStart, - } - automata[ElementDashStart] = []TokenType{ - IdentifierStart, TextFragment, - } - automata[ElementPlusStart] = []TokenType{ - TextFragment, - } - automata[Identifier] = []TokenType{ - IdentifierEnd, SectionStart, - } - automata[IdentifierStart] = []TokenType{ - Identifier, - } - automata[IdentifierEnd] = []TokenType{ - TextFragment, - } - automata[SectionIdentifierStart] = []TokenType{ - Identifier, - } - automata[SectionStart] = []TokenType{ - ElementDashStart, SectionIdentifierStart, EOF, - } - automata[SectionEnd] = []TokenType{ - SectionIdentifierStart, ElementDashStart, EOF, - } - automata[SOF] = []TokenType{ - ElementDashStart, SectionIdentifierStart, EOF, - } - automata[EOF] = []TokenType{} - return automata -} - -func validateGrammar() error { - for i := 0; i < len(tokens) - 1; i++ { - token := tokens[i] - content := token.content - if (token.tokenType == TextFragment) { - content = strings.Replace( - strings.Trim(content, " "), - "\n", - "\\n", - -1, - ) - } - nextToken := tokens[i + 1] - fmt.Printf( - "%s: \"%s\" %d:%d\n", - ToString(&token.tokenType), - content, - token.row, - token.column, - ) - if (false) { - fmt.Print("Possible next tokens:") - for k:=0; k= len(tokens)) { - break - } - if (tokens[i].tokenType == ElementDashStart) { - id := tokens[i + 2].content - question := tokens[i + 4].content - quesitonElements := []QuestionElement{} - i += 6 - for { - if (i + 1 >= len(tokens) || - !(tokens[i].tokenType == ElementDashStart || - tokens[i].tokenType == ElementPlusStart) || - tokens[i+1].tokenType == IdentifierStart) { - break - } - questionElement := QuestionElement{} - if (tokens[i].tokenType == ElementDashStart) { - questionElement.isDash = true - } else { - questionElement.isDash = false - } - questionElement.content = tokens[i+1].content - quesitonElements = append(quesitonElements, questionElement) - i += 2 - } - if len(quesitonElements) > 1 { - question := MultipleChoiceQuestion{ - id: id, - question: question, - } - choices := []Choice{} - for k := 0; k < len(quesitonElements); k++ { - choice := Choice{} - choice.answer = quesitonElements[k].content - choice.isCorrect = !quesitonElements[k].isDash - choices = append(choices, choice) - } - if (section != "") { - question.section = section - } - question.choices = choices - questions = append(questions, question) - } else if (len(quesitonElements) == 1) { - question := SingleAnswerQuestion{ - id: id, - question: question, - answer: quesitonElements[0].content, - } - if (section != "") { - question.section = section - } - questions = append(questions, question) - } - } else if (tokens[i].tokenType == SectionIdentifierStart) { - section = tokens[i + 1].content - i += 3; - } else if (tokens[i].tokenType == SectionEnd) { - section = "" - i += 1 - } else if (tokens[i].tokenType == EOF) { - break - } else { - log.Fatalf( - "Not handled: %s", - ToString(&tokens[i].tokenType), - ) - return nil, CompilerErr{ - message: "", - row: tokens[i].row, - column: tokens[i].column, - } - } - } - return questions, nil -} - func main() { log.Println("Compilation started") diff --git a/src/compiler/parser.go b/src/compiler/parser.go new file mode 100644 index 0000000..77f4c46 --- /dev/null +++ b/src/compiler/parser.go @@ -0,0 +1,218 @@ +package main + +import ( + "fmt" + "strings" + "log" +) + +type Question interface {} + +type SingleAnswerQuestion struct { + id string; + question string; + answer string; + section string; +} + +type Choice struct { + answer string; + isCorrect bool; +} + +type MultipleChoiceQuestion struct { + id string; + question string; + choices []Choice; + section string; +} + +type QuestionElement struct { + isDash bool; + content string; +} + +var automata map[TokenType][]TokenType + +type CompilerErr struct { + message string; + row int32; + column int32; +} + +func (e CompilerErr) Error() string { + return fmt.Sprintf("%d:%d - %s", e.row, e.column, e.message) +} + +func contains(s []TokenType, e TokenType) bool { + for _, a := range s { + if a == e { + return true + } + } + return false +} + +func parserAutomata() map[TokenType][]TokenType { + automata := make(map[TokenType][]TokenType) + automata[TextFragment] = []TokenType{ + QuestionEnd, ElementDashStart, ElementPlusStart, SectionIdentifierStart, SectionStart, EOF, SectionEnd, + } + automata[QuestionEnd] = []TokenType{ + ElementDashStart, ElementPlusStart, + } + automata[ElementDashStart] = []TokenType{ + IdentifierStart, TextFragment, + } + automata[ElementPlusStart] = []TokenType{ + TextFragment, + } + automata[Identifier] = []TokenType{ + IdentifierEnd, SectionStart, + } + automata[IdentifierStart] = []TokenType{ + Identifier, + } + automata[IdentifierEnd] = []TokenType{ + TextFragment, + } + automata[SectionIdentifierStart] = []TokenType{ + Identifier, + } + automata[SectionStart] = []TokenType{ + ElementDashStart, SectionIdentifierStart, EOF, + } + automata[SectionEnd] = []TokenType{ + SectionIdentifierStart, ElementDashStart, EOF, + } + automata[SOF] = []TokenType{ + ElementDashStart, SectionIdentifierStart, EOF, + } + automata[EOF] = []TokenType{} + return automata +} + +func validateGrammar() error { + for i := 0; i < len(tokens) - 1; i++ { + token := tokens[i] + content := token.content + if (token.tokenType == TextFragment) { + content = strings.Replace( + strings.Trim(content, " "), + "\n", + "\\n", + -1, + ) + } + nextToken := tokens[i + 1] + fmt.Printf( + "%s: \"%s\" %d:%d\n", + ToString(&token.tokenType), + content, + token.row, + token.column, + ) + if (false) { + fmt.Print("Possible next tokens:") + for k:=0; k= len(tokens)) { + break + } + if (tokens[i].tokenType == ElementDashStart) { + id := tokens[i + 2].content + question := tokens[i + 4].content + quesitonElements := []QuestionElement{} + i += 6 + for { + if (i + 1 >= len(tokens) || + !(tokens[i].tokenType == ElementDashStart || + tokens[i].tokenType == ElementPlusStart) || + tokens[i+1].tokenType == IdentifierStart) { + break + } + questionElement := QuestionElement{} + if (tokens[i].tokenType == ElementDashStart) { + questionElement.isDash = true + } else { + questionElement.isDash = false + } + questionElement.content = tokens[i+1].content + quesitonElements = append(quesitonElements, questionElement) + i += 2 + } + if len(quesitonElements) > 1 { + question := MultipleChoiceQuestion{ + id: id, + question: question, + } + choices := []Choice{} + for k := 0; k < len(quesitonElements); k++ { + choice := Choice{} + choice.answer = quesitonElements[k].content + choice.isCorrect = !quesitonElements[k].isDash + choices = append(choices, choice) + } + if (section != "") { + question.section = section + } + question.choices = choices + questions = append(questions, question) + } else if (len(quesitonElements) == 1) { + question := SingleAnswerQuestion{ + id: id, + question: question, + answer: quesitonElements[0].content, + } + if (section != "") { + question.section = section + } + questions = append(questions, question) + } + } else if (tokens[i].tokenType == SectionIdentifierStart) { + section = tokens[i + 1].content + i += 3; + } else if (tokens[i].tokenType == SectionEnd) { + section = "" + i += 1 + } else if (tokens[i].tokenType == EOF) { + break + } else { + log.Fatalf( + "Not handled: %s", + ToString(&tokens[i].tokenType), + ) + return nil, CompilerErr{ + message: "", + row: tokens[i].row, + column: tokens[i].column, + } + } + } + return questions, nil +} +