Skip to content

Commit 75f2f20

Browse files
committed
init commit
0 parents  commit 75f2f20

File tree

7 files changed

+1348
-0
lines changed

7 files changed

+1348
-0
lines changed

ast.go

Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
package excelformulaparser
2+
3+
import (
4+
"fmt"
5+
"strconv"
6+
"strings"
7+
)
8+
9+
type Token struct {
10+
Start, End Pos
11+
Type TokenType
12+
Raw string // The raw string value of the token
13+
}
14+
15+
func newToken(start, end Pos, t TokenType, raw string) *Token {
16+
return &Token{
17+
Start: start,
18+
End: end,
19+
Type: t,
20+
Raw: raw,
21+
}
22+
}
23+
24+
type TokenType int
25+
26+
const (
27+
Ident TokenType = iota + 1
28+
Number
29+
String
30+
BoolLiteral // TRUE or FALSE
31+
Exclamation // !
32+
BraceOpen // {
33+
BraceClose // }
34+
BracketOpen // [
35+
BracketClose // ]
36+
ParenOpen // (
37+
ParenClose // )
38+
Comma // ,
39+
Semicolon // ;
40+
Percent // %
41+
Exponentiation // ^
42+
Multiply // *
43+
Divide // /
44+
Plus // +
45+
Colon // :
46+
Minus // -
47+
Connect // &
48+
Equal // =
49+
NotEqual // <>
50+
LessThan // <
51+
GreaterThan // >
52+
LessThanOrEqual // <=
53+
GreaterThanOrEqual // >=
54+
Cell // e.g., A1, B2, etc
55+
AbsoluteRow // Absolute row reference (e.g., $1, $2)
56+
AbsoluteColumn // Absolute column reference (e.g., $A, $B)
57+
)
58+
59+
type Pos struct {
60+
Line, Column int
61+
}
62+
63+
func (p *Pos) nextLine() {
64+
p.Line++
65+
p.Column = 1
66+
}
67+
68+
func (p *Pos) nextColumn() {
69+
p.Column++
70+
}
71+
72+
func (p Pos) String() string {
73+
return "(" + strconv.Itoa(p.Line) + "," + strconv.Itoa(p.Column) + ")"
74+
}
75+
76+
func (p Pos) Left() Pos {
77+
if p.Column == 1 {
78+
return Pos{Line: p.Line - 1, Column: 0} // Previous line, column 0
79+
}
80+
return Pos{Line: p.Line, Column: p.Column - 1}
81+
}
82+
83+
type Node interface {
84+
Start() Pos // Returns the position of the expression in the source code
85+
End() Pos // Returns the end position of the expression in the source code
86+
String() string // Returns a string representation of the node
87+
cannotBeImplemented() // Ensure this interface cannot be implemented by other types
88+
}
89+
90+
type baseNode struct {
91+
start Pos
92+
end Pos
93+
}
94+
95+
func (e *baseNode) Start() Pos {
96+
return e.start
97+
}
98+
99+
func (e *baseNode) End() Pos {
100+
return e.end
101+
}
102+
103+
func (e *baseNode) cannotBeImplemented() {}
104+
105+
func newBaseNode(start, end Pos) *baseNode {
106+
return &baseNode{
107+
start: start,
108+
end: end,
109+
}
110+
}
111+
112+
var _ Node = (*FunCallExpr)(nil)
113+
var _ Node = (*BinaryExpr)(nil)
114+
var _ Node = (*UnaryExpr)(nil)
115+
var _ Node = (*LiteralExpr)(nil)
116+
var _ Node = (*IdentExpr)(nil)
117+
var _ Node = (*RangeExpr)(nil)
118+
119+
type FunCallExpr struct {
120+
*baseNode
121+
Name *Token // Function name token
122+
ParanOpen *Token
123+
Arguments []Node // Arguments can be any expression type
124+
ParanClose *Token
125+
}
126+
127+
func (f *FunCallExpr) String() string {
128+
var sb strings.Builder
129+
sb.WriteString("FunCallExpr(Name: ")
130+
sb.WriteString(f.Name.Raw)
131+
sb.WriteString(", Arguments: [")
132+
for i, arg := range f.Arguments {
133+
if i > 0 {
134+
sb.WriteString(", ")
135+
}
136+
sb.WriteString(arg.String())
137+
}
138+
sb.WriteString("])")
139+
return sb.String()
140+
}
141+
142+
type BinaryExpr struct {
143+
*baseNode
144+
Left Node // Left operand
145+
Operator *Token // Operator token (e.g., +, -, *, /)
146+
Right Node // Right operand
147+
}
148+
149+
func (b *BinaryExpr) String() string {
150+
return fmt.Sprintf("BinaryExpr(Left: %s, Operator: %s, Right: %s)", b.Left, b.Operator.Raw, b.Right)
151+
}
152+
153+
type UnaryExpr struct {
154+
*baseNode
155+
Operator *Token // Operator token (e.g., !, -)
156+
Operand Node // Operand expression
157+
}
158+
159+
func (u *UnaryExpr) String() string {
160+
return fmt.Sprintf("UnaryExpr(Operator: %s, Operand: %s)", u.Operator.Raw, u.Operand)
161+
}
162+
163+
type LiteralExpr struct {
164+
*baseNode
165+
Value *Token // Token representing the literal value (e.g., number, string, boolean)
166+
}
167+
168+
func (l *LiteralExpr) String() string {
169+
return fmt.Sprintf("LiteralExpr(Value: %s)", l.Value.Raw)
170+
}
171+
172+
type IdentExpr struct {
173+
*baseNode
174+
Name *Token
175+
}
176+
177+
func (i *IdentExpr) String() string {
178+
return fmt.Sprintf("IdentExpr(Name: %s)", i.Name.Raw)
179+
}
180+
181+
type ParenthesizedExpr struct {
182+
*baseNode
183+
ParenOpen *Token // The opening parenthesis
184+
Inner Node // The expression inside the parentheses
185+
ParenClose *Token // The closing parenthesis
186+
}
187+
188+
func (p *ParenthesizedExpr) String() string {
189+
return fmt.Sprintf("ParenthesizedExpr(Inner: %s)", p.Inner)
190+
}
191+
192+
type RangeExpr struct {
193+
*baseNode
194+
195+
Begin Node // Start of the range (e.g., A1, A, 1)
196+
Colons []*Token // Colon tokens (e.g., : between A1 and B2)
197+
Ends []Node // End of the range (e.g., B2, B, 2)
198+
}
199+
200+
func (r *RangeExpr) String() string {
201+
var sb strings.Builder
202+
sb.WriteString("RangeExpr(")
203+
sb.WriteString(r.Begin.String())
204+
for _, end := range r.Ends {
205+
sb.WriteString(":")
206+
sb.WriteString(end.String())
207+
}
208+
sb.WriteString(")")
209+
return sb.String()
210+
}
211+
212+
type CellExpr struct {
213+
*baseNode
214+
Ident *Token // The cell identifier (e.g., A1, B2)
215+
Row int // starts from 0. -1 indicates a full column reference (e.g., A:A)
216+
Col int // starts from 0. -1 indicates a full row reference (e.g., 1:1)
217+
RowAbsolute bool // true if the row is absolute (e.g., $1, $2)
218+
ColAbsolute bool // true if the column is absolute (e.g., $A, $B)
219+
}
220+
221+
func (c *CellExpr) String() string {
222+
return fmt.Sprintf("CellExpr(%s)", c.Ident.Raw)
223+
}
224+
225+
type AbsoluteRowExpr struct {
226+
*baseNode
227+
Ident *Token // The absolute row reference (e.g., $1, $2)
228+
Row int // starts from 0
229+
}
230+
231+
func (a *AbsoluteRowExpr) String() string {
232+
return fmt.Sprintf("AbsoluteRowExpr(%s)", a.Ident.Raw)
233+
}
234+
235+
type AbsoluteColExpr struct {
236+
*baseNode
237+
Ident *Token // The absolute column reference (e.g., $A, $B)
238+
Col int // starts from 0
239+
}
240+
241+
func (a *AbsoluteColExpr) String() string {
242+
return fmt.Sprintf("AbsoluteColExpr(%s)", a.Ident.Raw)
243+
}

errors.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package excelformulaparser
2+
3+
import "fmt"
4+
5+
type LexError struct {
6+
Pos Pos
7+
Message string
8+
}
9+
10+
func (e *LexError) Error() string {
11+
return fmt.Sprintf("%s: %s", e.Pos, e.Message)
12+
}
13+
14+
func newLexError(pos Pos, format string, args ...interface{}) *LexError {
15+
return &LexError{
16+
Pos: pos,
17+
Message: fmt.Sprintf(format, args...),
18+
}
19+
}
20+
21+
type ParseError struct {
22+
Pos Pos
23+
Message string
24+
}
25+
26+
func newParseError(pos Pos, format string, args ...interface{}) *ParseError {
27+
return &ParseError{
28+
Pos: pos,
29+
Message: fmt.Sprintf(format, args...),
30+
}
31+
}
32+
33+
func (e *ParseError) Error() string {
34+
return fmt.Sprintf("%s: %s", e.Pos, e.Message)
35+
}

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module github.com/link-duan/excel-formula-parser
2+
3+
go 1.24.3

0 commit comments

Comments
 (0)