mirror of
https://github.com/jorenchik/mdemory.git
synced 2026-03-22 00:26:21 +00:00
output and error handling
This commit is contained in:
1
src/compiler/.gitignore
vendored
Normal file
1
src/compiler/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
compiler
|
||||||
@@ -2,36 +2,37 @@ 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")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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))
|
|
||||||
|
func ParseQuestions(tokens []lexer.Token) ([]Question, error) {
|
||||||
|
err := ValidateGrammar(tokens)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if true {
|
|
||||||
log.Println("Lexer output:")
|
|
||||||
for _, el := range tokens {
|
|
||||||
fmt.Print(el.ToString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err = ValidateGrammar(tokens)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user