-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpasgo.go
More file actions
109 lines (96 loc) · 2.43 KB
/
pasgo.go
File metadata and controls
109 lines (96 loc) · 2.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// https://www.tutorialspoint.com/pascal/pascal_program_structure.htm
package main
import (
"bufio"
"flag"
"fmt"
"os"
"regexp"
"strings"
)
func usage() {
fmt.Fprintf(os.Stderr, "usage: %s <file>.pas\n", os.Args[0])
flag.PrintDefaults()
os.Exit(2)
}
// Unless you need to deal with advanced grammar,
// I recommend just implementing a simple recursive
// descent parser and not bothering with formalisms.
// 17+6 5*(3+7) -> 5*(10) -> 50
// shunting-yard algorithm
// https://www.freepascal.org/docs-html/ref/refch12.html
// https://tiarkrompf.github.io/notes/?/just-write-the-parser/
func evaluateExpression(expression string) (int, error) {
expression = strings.ReplaceAll(expression, " ", "")
// var result int
// switch operator {
// case "div":
// result = a / b
// case "mod":
// result
// }
return 0, nil
}
func main() {
if len(os.Args) != 2 {
usage()
}
fileName := os.Args[1]
file, err := os.Open(fileName)
if err != nil {
fmt.Printf("Unable to open %s.\n", fileName)
return
}
defer file.Close()
scanner := bufio.NewScanner(file)
i := 0
var programName string
var block bool = false
for scanner.Scan() {
currentLine := scanner.Text()
currentLine = strings.TrimSpace(currentLine)
// fmt.Printf("Line %d: %s\n", i, currentLine)
// line 1
if strings.HasPrefix(currentLine, "program") {
fields := strings.Fields(currentLine)
if len(fields) == 2 {
programName = strings.TrimSuffix(fields[1], ";")
fmt.Println("ProgramName:", programName)
} else {
fmt.Printf("ProgramName: Error! %s\n", currentLine)
return
}
} else if currentLine == "begin" {
block = true
} else if strings.Contains(currentLine, "writeln") {
re := regexp.MustCompile(`\((.*?)\)`)
match := re.FindStringSubmatch(currentLine)
// TODO: evaluating the argument and ensuring that it handles things like variables, expressions, and newlines—is the next step.
if len(match) > 1 {
arg := match[1]
// fmt.Println(arg) //[1 : len(arg)-1])
result, err := evaluateExpression(arg)
if err != nil {
fmt.Println("Error evaluating expression %s\n", err)
return
}
fmt.Println(result)
// return
} else {
fmt.Printf("WriteLn: Error! %s\n", currentLine)
return
}
} else if currentLine == "end." {
if !block {
fmt.Println("No begin: Error!")
return
}
block = false
break
}
i++
}
if err := scanner.Err(); err != nil {
fmt.Println("Scanner: Error!")
}
}