output and error handling

This commit is contained in:
jorenchik
2024-09-07 13:37:07 +03:00
parent 0a09831d17
commit 42e4d93ae2
4 changed files with 75 additions and 44 deletions

1
src/compiler/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
compiler

View File

@@ -1,37 +1,38 @@
package main package main
import ( import (
"fmt" "fmt"
"log"
"os" "os"
"github.com/jorenchik/mdemory/src/compiler/parser" "github.com/jorenchik/mdemory/src/compiler/parser"
"github.com/jorenchik/mdemory/src/compiler/lexer"
) )
func main() { func main() {
log.Println("Compilation started") fmt.Println("Compilation started...")
file, err := os.ReadFile( file, err := os.ReadFile(
"/home/jorenchik/Code/mdemory/src/compiler/input.mdem", "/home/jorenchik/Code/mdemory/src/compiler/input.mdem",
) )
if (err != nil) { if (err != nil) {
log.Fatalf( fmt.Printf(
"Cannot open the input file: %s", "Cannot open the input file: %s\n",
err.Error(), err.Error(),
) )
return return
} }
fileContents := string(file) fileContents := string(file)
questions, err := parser.ParseQuestions(fileContents) tokens, err := lexer.TokenizeMdem([]rune(fileContents))
if (err != nil) { if err != nil {
log.Fatal(err.Error()) fmt.Println(err.Error())
} return
if (true) {
log.Println("Parser output:")
for _, element := range questions {
fmt.Printf("%s", element.ToString())
}
} }
log.Println("Compilation completed") _, err = parser.ParseQuestions(tokens)
if (err != nil) {
fmt.Println(err.Error())
return
}
fmt.Println("Compilation completed")
} }

View File

@@ -164,6 +164,14 @@ func TokenizeMdem(fileRunes []rune) ( []Token, error ) {
// EmitEOF // EmitEOF
makeTokenWithTokenBuffer(EOF, 0, TextFragment) makeTokenWithTokenBuffer(EOF, 0, TextFragment)
if true {
fmt.Printf("Lexer output:\n")
for _, el := range tokens {
fmt.Print(el.ToString())
}
fmt.Printf("End Lexer output\n")
}
return tokens, nil return tokens, nil
} }

View File

@@ -2,9 +2,9 @@ package parser
import ( import (
"fmt" "fmt"
"github.com/jorenchik/mdemory/src/compiler/lexer"
"log"
"strings" "strings"
"github.com/jorenchik/mdemory/src/compiler/lexer"
) )
type Question interface { type Question interface {
@@ -32,7 +32,7 @@ type MultipleChoiceQuestion struct {
func (question SingleAnswerQuestion) ToString() string { func (question SingleAnswerQuestion) ToString() string {
return fmt.Sprintf( return fmt.Sprintf(
"%20s: section: %-10s id: %-10s %-30s: %-30s\n", "%20s: section: %-10s id: %-10s %-30s: %-30s",
"<Single choice>", "<Single choice>",
question.Section, question.Section,
question.ID, question.ID,
@@ -44,7 +44,7 @@ func (question SingleAnswerQuestion) ToString() string {
func (question MultipleChoiceQuestion) ToString() string { func (question MultipleChoiceQuestion) ToString() string {
acc := "" acc := ""
acc += fmt.Sprintf( acc += fmt.Sprintf(
"%20s: section: %-10s id: %-10s %-30s\n", "%20s: section: %-10s id: %-10s %-30s",
"<Multi choice>", "<Multi choice>",
question.section, question.section,
question.id, question.id,
@@ -98,16 +98,19 @@ func parserAutomata() map[lexer.TokenType][]lexer.TokenType {
lexer.SectionEnd, lexer.SectionEnd,
} }
automata[lexer.QuestionEnd] = []lexer.TokenType{ automata[lexer.QuestionEnd] = []lexer.TokenType{
lexer.ElementDashStart, lexer.ElementPlusStart, lexer.ElementDashStart,
lexer.ElementPlusStart,
} }
automata[lexer.ElementDashStart] = []lexer.TokenType{ automata[lexer.ElementDashStart] = []lexer.TokenType{
lexer.IdentifierStart, lexer.TextFragment, lexer.IdentifierStart,
lexer.TextFragment,
} }
automata[lexer.ElementPlusStart] = []lexer.TokenType{ automata[lexer.ElementPlusStart] = []lexer.TokenType{
lexer.TextFragment, lexer.TextFragment,
} }
automata[lexer.Identifier] = []lexer.TokenType{ automata[lexer.Identifier] = []lexer.TokenType{
lexer.IdentifierEnd, lexer.SectionStart, lexer.IdentifierEnd,
lexer.SectionStart,
} }
automata[lexer.IdentifierStart] = []lexer.TokenType{ automata[lexer.IdentifierStart] = []lexer.TokenType{
lexer.Identifier, lexer.Identifier,
@@ -119,13 +122,19 @@ func parserAutomata() map[lexer.TokenType][]lexer.TokenType {
lexer.Identifier, lexer.Identifier,
} }
automata[lexer.SectionStart] = []lexer.TokenType{ automata[lexer.SectionStart] = []lexer.TokenType{
lexer.ElementDashStart, lexer.SectionIdentifierStart, lexer.EOF, lexer.ElementDashStart,
lexer.SectionIdentifierStart,
lexer.EOF,
} }
automata[lexer.SectionEnd] = []lexer.TokenType{ automata[lexer.SectionEnd] = []lexer.TokenType{
lexer.SectionIdentifierStart, lexer.ElementDashStart, lexer.EOF, lexer.SectionIdentifierStart,
lexer.ElementDashStart,
lexer.EOF,
} }
automata[lexer.SOF] = []lexer.TokenType{ automata[lexer.SOF] = []lexer.TokenType{
lexer.ElementDashStart, lexer.SectionIdentifierStart, lexer.EOF, lexer.ElementDashStart,
lexer.SectionIdentifierStart,
lexer.EOF,
} }
automata[lexer.EOF] = []lexer.TokenType{} automata[lexer.EOF] = []lexer.TokenType{}
return automata return automata
@@ -151,26 +160,20 @@ func ValidateGrammar(tokens []lexer.Token) error {
return nil return nil
} }
func ParseQuestions(fileContents string) ([]Question, error) { var DEBUG bool = true
tokens, err := lexer.TokenizeMdem([]rune(fileContents))
if err != nil {
return nil, err
}
if true {
log.Println("Lexer output:")
for _, el := range tokens {
fmt.Print(el.ToString())
}
}
err = ValidateGrammar(tokens) func ParseQuestions(tokens []lexer.Token) ([]Question, error) {
err := ValidateGrammar(tokens)
if err != nil { if err != nil {
log.Fatal(err.Error()) return nil, err
} }
questions := []Question{} questions := []Question{}
section := "" section := ""
i := 0 i := 0
if DEBUG {
fmt.Printf("Parser output:\n")
}
for { for {
if i >= len(tokens) { if i >= len(tokens) {
break break
@@ -212,6 +215,13 @@ func ParseQuestions(fileContents string) ([]Question, error) {
tokens[i + offset].TokenType == lexer.QuestionEnd { tokens[i + offset].TokenType == lexer.QuestionEnd {
break break
} }
if offset == 5 && tokens[i + 5].TokenType != lexer.QuestionEnd {
return nil, CompilerErr{
message: "Cannot have an identifier here",
row: tokens[i].Row,
column: tokens[i].Column,
}
}
} }
if (i + 2 >= len(tokens)) { if (i + 2 >= len(tokens)) {
break; break;
@@ -243,6 +253,9 @@ func ParseQuestions(fileContents string) ([]Question, error) {
} }
question.choices = choices question.choices = choices
questions = append(questions, question) questions = append(questions, question)
if DEBUG {
fmt.Printf("%s", question.ToString())
}
} else if len(questionElements) == 1 { } else if len(questionElements) == 1 {
question := SingleAnswerQuestion{ question := SingleAnswerQuestion{
ID: id, ID: id,
@@ -253,22 +266,30 @@ func ParseQuestions(fileContents string) ([]Question, error) {
question.Section = section question.Section = section
} }
questions = append(questions, question) questions = append(questions, question)
if DEBUG {
fmt.Printf("%s\n", question.ToString())
}
} }
} else if tokens[i].TokenType == lexer.SectionIdentifierStart { } else if tokens[i].TokenType == lexer.SectionIdentifierStart {
section = tokens[i+1].Content section = tokens[i + 1].Content
i += 3 i += 3
if DEBUG {
fmt.Printf("Started section: %s\n", section)
}
} else if tokens[i].TokenType == lexer.SectionEnd { } else if tokens[i].TokenType == lexer.SectionEnd {
section = "" section = ""
i += 1 i += 1
if DEBUG {
fmt.Printf("Section ended: %s\n", section)
}
} else if tokens[i].TokenType == lexer.EOF { } else if tokens[i].TokenType == lexer.EOF {
if DEBUG {
fmt.Printf("File terminated: EOF\n")
}
break break
} else { } else {
log.Fatalf(
"Not handled: %s",
lexer.ToString(&tokens[i].TokenType),
)
return nil, CompilerErr{ return nil, CompilerErr{
message: "", message: "Unexpeced token: %s",
row: tokens[i].Row, row: tokens[i].Row,
column: tokens[i].Column, column: tokens[i].Column,
} }