-
Notifications
You must be signed in to change notification settings - Fork 0
/
frontend.ict.go
126 lines (103 loc) · 3.95 KB
/
frontend.ict.go
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// Package fe contains the frontend for analyzing FISHI
// code. The function [Frontend] is the primary entrypoint for callers, and will
// return a full FISHI frontend ready for immediate use.
package fe
/*
File automatically generated by the ictiobus compiler. DO NOT EDIT. This was
created by invoking ictiobus with the following command:
ictcc --lalr --ir github.com/dekarrin/ictiobus/fishi/syntax.AST --dest fishi/fe -l FISHI -v 1.0 --hooks fishi/syntax docs/fishi.md --dev
*/
import (
"fmt"
"os"
"strings"
"github.com/dekarrin/ictiobus"
"github.com/dekarrin/ictiobus/lex"
"github.com/dekarrin/ictiobus/trans"
"github.com/dekarrin/ictiobus/fishi/syntax"
)
// FrontendOptions allows options to be set on the compiler frontend returned by
// [Frontend]. It allows setting of debug flags and other optional
// functionality.
type FrontendOptions struct {
// LexerEager is whether the Lexer should immediately read all input the
// first time it is called. The default is lazy lexing, where the minimum
// number of tokens are read when required by the parser.
LexerEager bool
// LexerTrace is whether to add tracing functionality to the lexer. This
// will cause the tokens to be printed to stderr as they are lexed. Note
// that with LexerEager set, this implies that they will all be lexed and
// therefore printed before any parsing occurs.
LexerTrace bool
// ParserTrace is whether to add tracing functionality to the parser. This
// will cause parsing events to be printed to stderr as they occur. This
// includes operations such as token or symbol stack manipulation, and for
// LR parsers, shifts and reduces.
ParserTrace bool
// SDTSTrace is whether to add tracing functionality to the translation
// scheme. This will cause translation events to be printed to stderr as
// they occur. This includes operations such as parse tree annotation and
// hook execution.
SDTSTrace bool
}
// Frontend returns the complete compiled frontend for the FISHI langauge.
// The hooks map must be provided as it is the interface between the translation
// scheme in the frontend and the external code executed in the backend. The
// opts parameter allows options to be set on the frontend for debugging and
// other purposes. If opts is nil, it is treated as an empty FrontendOptions.
func Frontend(hooks trans.HookMap, opts *FrontendOptions) ictiobus.Frontend[syntax.AST] {
if opts == nil {
opts = &FrontendOptions{}
}
fe := ictiobus.Frontend[syntax.AST]{
Language: "FISHI",
Version: "1.0",
IRAttribute: "ast",
Lexer: Lexer(!opts.LexerEager),
Parser: Parser(),
SDTS: SDTS(),
}
// Add traces if requested
if opts.LexerTrace {
fe.Lexer.RegisterTraceListener(func(t lex.Token) {
fmt.Fprintf(os.Stderr, "Token: %s\n", t)
})
}
if opts.ParserTrace {
fe.Parser.RegisterTraceListener(func(s string) {
fmt.Fprintf(os.Stderr, "Parser: %s\n", s)
})
}
if opts.SDTSTrace {
fe.SDTS.RegisterListener(func(e trans.Event) {
switch e.Type {
case trans.EventAnnotation:
fmt.Fprintf(os.Stderr, "SDTS: Annotated parse tree:\n%s\n", e.Tree)
case trans.EventHookCall:
relNode, ok := e.Hook.Node.RelativeNode(e.Hook.Target.Rel)
if !ok {
panic("bad relative node in SDTS hook call event")
}
var argSb strings.Builder
for i := range e.Hook.Args {
argSb.WriteString(fmt.Sprintf("%#v", e.Hook.Args[i].Value))
if i+1 < len(e.Hook.Args) {
argSb.WriteString(", ")
}
}
message := fmt.Sprintf("SDTS: Set (%d: %s).%s = %s(%s) = ", relNode.ID(), relNode.Symbol, e.Hook.Target.Name, e.Hook.Name, argSb.String())
if e.Hook.Result.Error != nil {
message += fmt.Sprintf("ERROR(%v) (with value %#v)", e.Hook.Result.Error.Error(), e.Hook.Result.Value)
} else {
message += fmt.Sprintf("%#v", e.Hook.Result.Value)
}
fmt.Fprintf(os.Stderr, "%s\n", message)
default:
fmt.Fprintf(os.Stderr, "SDTS: %v\n", e)
}
})
}
// Set the hooks
fe.SDTS.SetHooks(hooks)
return fe
}