Parser refactoring

This commit is contained in:
jorenchik
2024-08-04 15:06:24 +03:00
parent 64a250bb77
commit 70db69ed88

View File

@@ -7,7 +7,7 @@ import (
"strings"
)
var automata map[TokenType][]TokenType
type Question interface {}
type SingleAnswerQuestion struct {
id string;
@@ -21,33 +21,41 @@ type Choice struct {
isCorrect bool;
}
type ChoiceQuestion struct {
type MultipleChoiceQuestion struct {
id string;
question string;
choices []Choice;
section string;
}
type Question interface {}
type QuestionElement struct {
isDash bool;
content string;
}
func main() {
log.Println("Compilation started")
var automata map[TokenType][]TokenType
file, err := os.ReadFile("/home/jorenchik/Code/mdemory/src/compiler/input.mdem")
if (err != nil) {
log.Fatalf("Cannot open the input file: %s", err.Error())
return
}
fileContents := string(file)
type CompilerErr struct {
message string;
row int32;
column int32;
}
tokens, err := tokenize([]rune(fileContents))
if (err != nil) {
fmt.Printf("%s\n", err.Error())
return
}
func (e CompilerErr) Error() string {
return fmt.Sprintf("%d:%d - %s", e.row, e.column, e.message)
}
// defineParserAutomata
automata = make(map[TokenType][]TokenType)
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,
}
@@ -82,8 +90,10 @@ func main() {
ElementDashStart, SectionIdentifierStart, EOF,
}
automata[EOF] = []TokenType{}
return automata
}
// validateGrammar
func validateGrammar() error {
for i := 0; i < len(tokens) - 1; i++ {
token := tokens[i]
content := token.content
@@ -112,16 +122,21 @@ func main() {
fmt.Print("\n:")
}
if (!contains(automata[token.tokenType], nextToken.tokenType)) {
fmt.Printf(
"Token %s cannot precede %s\n",
ToString(&token.tokenType),
ToString(&nextToken.tokenType),
)
return
return CompilerErr{
message: fmt.Sprintf(
"Token %s cannot precede %s\n",
ToString(&token.tokenType),
ToString(&nextToken.tokenType),
),
row: token.row,
column: token.column,
}
}
}
return nil
}
// extract questions
func ParseQuestions(tokens []Token) ([]Question, error) {
questions := []Question{}
section := ""
i := 0
@@ -152,7 +167,7 @@ func main() {
i += 2
}
if len(quesitonElements) > 1 {
question := ChoiceQuestion{
question := MultipleChoiceQuestion{
id: id,
question: question,
}
@@ -192,10 +207,42 @@ func main() {
"Not handled: %s",
ToString(&tokens[i].tokenType),
)
return
return nil, CompilerErr{
message: "",
row: tokens[i].row,
column: tokens[i].column,
}
}
}
return questions, nil
}
func main() {
log.Println("Compilation started")
file, err := os.ReadFile("/home/jorenchik/Code/mdemory/src/compiler/input.mdem")
if (err != nil) {
log.Fatalf("Cannot open the input file: %s", err.Error())
return
}
fileContents := string(file)
tokens, err := tokenize([]rune(fileContents))
if (err != nil) {
fmt.Printf("%s\n", err.Error())
return
}
automata = parserAutomata()
err = validateGrammar()
if (err != nil) {
log.Fatal(err.Error())
}
questions, err := ParseQuestions(tokens)
if (err != nil) {
log.Fatal(err.Error())
}
for _, element := range questions {
switch element.(type) {
case SingleAnswerQuestion:
@@ -205,13 +252,13 @@ func main() {
strings.Trim(element.(SingleAnswerQuestion).question, "\t\n "),
strings.Trim(element.(SingleAnswerQuestion).answer, "\t\n "),
)
case ChoiceQuestion:
case MultipleChoiceQuestion:
fmt.Printf(
"<Multi choice> (%s) %s\n",
element.(ChoiceQuestion).section,
element.(ChoiceQuestion).question,
element.(MultipleChoiceQuestion).section,
element.(MultipleChoiceQuestion).question,
)
for _, el := range element.(ChoiceQuestion).choices {
for _, el := range element.(MultipleChoiceQuestion).choices {
opener := '-'
if (el.isCorrect) {
opener = '+'
@@ -223,28 +270,3 @@ func main() {
log.Println("Compilation completed")
}
type QuestionElement struct {
isDash bool;
content string;
}
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
}