Example #1
0
func TestWalk(t *testing.T) {
	g := ast.Grammar([]*ast.Production{
		{
			Name: &ast.Name{Name: "E"},
			Expr: ast.Alternative([]ast.Expression{
				ast.Sequence([]ast.Expression{
					&ast.Name{Name: "T"},
					&ast.Terminal{Terminal: "+"},
					&ast.Name{Name: "T"},
				}),
				&ast.Name{Name: "T"},
				&ast.Epsilon{Epsilon: "e"},
			}),
		},
		{
			Name: &ast.Name{Name: "T"},
			Expr: ast.Alternative([]ast.Expression{
				ast.Sequence([]ast.Expression{
					&ast.Terminal{Terminal: "("},
					&ast.Name{Name: "T"},
					&ast.Terminal{Terminal: ")"},
				}),
				&ast.Name{Name: "T"},
			}),
		},
	})

	order := []string{
		"ast.Grammar",
		"*ast.Production",
		"*ast.Name",
		"ast.Alternative",
		"ast.Sequence",
		"*ast.Name",
		"*ast.Terminal",
		"*ast.Name",
		"*ast.Name",
		"*ast.Epsilon",
		"*ast.Production",
		"*ast.Name",
		"ast.Alternative",
		"ast.Sequence",
		"*ast.Terminal",
		"*ast.Name",
		"*ast.Terminal",
		"*ast.Name",
	}

	i := 0
	ast.Walk(func(n ast.Node) bool {
		if n == nil {
			return false
		}
		if typ := reflect.TypeOf(n).String(); order[i] != typ {
			t.Errorf("got %q want %q", typ, order[i])
		}
		i++
		return true
	}, g)
}
Example #2
0
func TestFprint(t *testing.T) {
	const expected = `Expr → Term "+" Expr | Term "-" Expr | Term | ε .
Term → Factor "*" Term | Factor "/" Term | Factor .
Factor → "(" Expr ")" | Number .
Number → Digit | Digit Number .
Digit → "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" .`

	g := ast.Grammar([]*ast.Production{
		{
			Name: &ast.Name{Name: "Expr"},
			Expr: ast.Alternative([]ast.Expression{
				ast.Sequence([]ast.Expression{
					&ast.Name{Name: "Term"},
					&ast.Terminal{Terminal: "+"},
					&ast.Name{Name: "Expr"},
				}),
				ast.Sequence([]ast.Expression{
					&ast.Name{Name: "Term"},
					&ast.Terminal{Terminal: "-"},
					&ast.Name{Name: "Expr"},
				}),
				&ast.Name{Name: "Term"},
				&ast.Epsilon{Epsilon: "e"},
			}),
		},
		{
			Name: &ast.Name{Name: "Term"},
			Expr: ast.Alternative([]ast.Expression{
				ast.Sequence([]ast.Expression{
					&ast.Name{Name: "Factor"},
					&ast.Terminal{Terminal: "*"},
					&ast.Name{Name: "Term"},
				}),
				ast.Sequence([]ast.Expression{
					&ast.Name{Name: "Factor"},
					&ast.Terminal{Terminal: "/"},
					&ast.Name{Name: "Term"},
				}),
				&ast.Name{Name: "Factor"},
			}),
		},
		{
			Name: &ast.Name{Name: "Factor"},
			Expr: ast.Alternative([]ast.Expression{
				ast.Sequence([]ast.Expression{
					&ast.Terminal{Terminal: "("},
					&ast.Name{Name: "Expr"},
					&ast.Terminal{Terminal: ")"},
				}),
				&ast.Name{Name: "Number"},
			}),
		},
		{
			Name: &ast.Name{Name: "Number"},
			Expr: ast.Alternative([]ast.Expression{
				&ast.Name{Name: "Digit"},
				ast.Sequence([]ast.Expression{
					&ast.Name{Name: "Digit"},
					&ast.Name{Name: "Number"},
				}),
			}),
		},
		{
			Name: &ast.Name{Name: "Digit"},
			Expr: ast.Alternative([]ast.Expression{
				&ast.Terminal{Terminal: "0"}, &ast.Terminal{Terminal: "1"},
				&ast.Terminal{Terminal: "2"}, &ast.Terminal{Terminal: "3"},
				&ast.Terminal{Terminal: "4"}, &ast.Terminal{Terminal: "5"},
				&ast.Terminal{Terminal: "6"}, &ast.Terminal{Terminal: "7"},
				&ast.Terminal{Terminal: "8"}, &ast.Terminal{Terminal: "9"},
			}),
		},
	})

	var buf bytes.Buffer
	if err := printer.Fprint(&buf, g); err != nil {
		t.Errorf("error: %v", err)
	}
	if actual := buf.String(); actual != expected {
		t.Errorf("got\n'%s'\nwant\n'%s'", actual, expected)
	}
}
Example #3
0
func TestParse(t *testing.T) {
	const src = `Start -> Expr.
Expr → Term "+" Expr | Term "-" Expr | Term | ε.
Term → Factor "*" Term | Factor "/" Term | Factor .
Factor → "(" Expr ")" | Number .
Number → Digit | Digit Number .
Digit → "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" .`

	expected := ast.Grammar([]*ast.Production{
		{
			Name: &ast.Name{Name: "Start"},
			Expr: &ast.Name{Name: "Expr"},
		},
		{
			Name: &ast.Name{Name: "Expr"},
			Expr: ast.Alternative([]ast.Expression{
				ast.Sequence([]ast.Expression{
					&ast.Name{Name: "Term"},
					&ast.Terminal{Terminal: "+"},
					&ast.Name{Name: "Expr"},
				}),
				ast.Sequence([]ast.Expression{
					&ast.Name{Name: "Term"},
					&ast.Terminal{Terminal: "-"},
					&ast.Name{Name: "Expr"},
				}),
				&ast.Name{Name: "Term"},
				&ast.Epsilon{Epsilon: "ε"},
			}),
		},
		{
			Name: &ast.Name{Name: "Term"},
			Expr: ast.Alternative([]ast.Expression{
				ast.Sequence([]ast.Expression{
					&ast.Name{Name: "Factor"},
					&ast.Terminal{Terminal: "*"},
					&ast.Name{Name: "Term"},
				}),
				ast.Sequence([]ast.Expression{
					&ast.Name{Name: "Factor"},
					&ast.Terminal{Terminal: "/"},
					&ast.Name{Name: "Term"},
				}),
				&ast.Name{Name: "Factor"},
			}),
		},
		{
			Name: &ast.Name{Name: "Factor"},
			Expr: ast.Alternative([]ast.Expression{
				ast.Sequence([]ast.Expression{
					&ast.Terminal{Terminal: "("},
					&ast.Name{Name: "Expr"},
					&ast.Terminal{Terminal: ")"},
				}),
				&ast.Name{Name: "Number"},
			}),
		},
		{
			Name: &ast.Name{Name: "Number"},
			Expr: ast.Alternative([]ast.Expression{
				&ast.Name{Name: "Digit"},
				ast.Sequence([]ast.Expression{
					&ast.Name{Name: "Digit"},
					&ast.Name{Name: "Number"},
				}),
			}),
		},
		{
			Name: &ast.Name{Name: "Digit"},
			Expr: ast.Alternative([]ast.Expression{
				&ast.Terminal{Terminal: "0"}, &ast.Terminal{Terminal: "1"},
				&ast.Terminal{Terminal: "2"}, &ast.Terminal{Terminal: "3"},
				&ast.Terminal{Terminal: "4"}, &ast.Terminal{Terminal: "5"},
				&ast.Terminal{Terminal: "6"}, &ast.Terminal{Terminal: "7"},
				&ast.Terminal{Terminal: "8"}, &ast.Terminal{Terminal: "9"},
			}),
		},
	})

	g, err := parser.Parse([]byte(src), "test")
	if err != nil {
		t.Errorf("error: %v", err)
	}
	check(t, g, expected)
}
Example #4
0
var testGrammar = ast.Grammar([]*ast.Production{
	{
		Name: &ast.Name{Name: "E"},
		Expr: ast.Alternative([]ast.Expression{
			&ast.Name{Name: "T"},
			ast.Sequence([]ast.Expression{
				&ast.Name{Name: "E"},
				&ast.Terminal{Terminal: "+"},
				&ast.Name{Name: "T"},
			}),
		}),
	},
	{
		Name: &ast.Name{Name: "T"},
		Expr: ast.Alternative([]ast.Expression{
			&ast.Name{Name: "F"},
			ast.Sequence([]ast.Expression{
				&ast.Name{Name: "T"},
				&ast.Terminal{Terminal: "*"},
				&ast.Name{Name: "F"},
			}),
		}),
	},
	{
		Name: &ast.Name{Name: "F"},
		Expr: ast.Alternative([]ast.Expression{
			ast.Sequence([]ast.Expression{
				&ast.Terminal{Terminal: "("},
				&ast.Name{Name: "E"},
				&ast.Terminal{Terminal: ")"},
			}),
			&ast.Terminal{Terminal: "id"},
		}),
	},
})