Пример #1
0
func gen(args []string) {
	flags := flag.NewFlagSet("", flag.ExitOnError)
	out := flags.String("o", "out.go", "output file")

	if len(args) == 0 {
		log.SetPrefix("")
		log.Fatal("Usage: pg gen [flags] <file>\nFlags:\n\t-o output file (instead of out.go)")
	}
	in := args[len(args)-1]
	flags.Parse(args[:len(args)-1])

	f, err := os.Open(in)
	if err != nil {
		log.Fatalf("cannot open file: %v", err)
	}
	defer f.Close()

	src, err := ioutil.ReadAll(f)
	if err != nil {
		log.Fatalf("cannot read file: %v", err)
	}

	g, err := parser.Parse(src, in)
	if err != nil {
		log.Fatalf(err.Error())
	}

	buf, err := generator.GenerateSLR(g)
	if err != nil {
		log.Fatalf(err.Error())
	}
	if err = ioutil.WriteFile(*out, buf, 0644); err != nil {
		log.Fatalf("cannot write file: %v", err)
	}
}
Пример #2
0
func TestParseErrors(t *testing.T) {
	errors := []struct {
		src string
		err string
	}{
		{"E E E", `test:1:3: expected →, got E (and 1 more error)`},
		{"E ->", `test:1:5: expected an expression (and 1 more error)`},
		{"E -> .", `test:1:6: expected an expression`},
		{"E -> T ", `test:1:8: production not terminated with . (and 1 more error)`},
		{"E -> T | | D | | .", `test:1:10: expected an expression (and 4 more errors)`},
		{"E -> T | | D.", `test:1:10: expected an expression (and 2 more errors)`},
		{"E -> T F -> D.", `test:1:10: unexpected -> (and 3 more errors)`},
		{`"foo"`, `test:1:1: expected a production, got "foo"`},
		{"?", `test:1:1: syntax error: illegal character U+003F '?'`},
	}

	for i, e := range errors {
		_, err := parser.Parse([]byte(e.src), "test")
		if err == nil {
			t.Errorf("%d: got no error, want %q", i, e.err)
		} else if err.Error() != e.err {
			t.Errorf("%d: got error %q, want %q", i, err.Error(), e.err)
		}
	}
}
Пример #3
0
func format(args []string) {
	flags := flag.NewFlagSet("", flag.ExitOnError)
	write := flags.Bool("w", false, "write to file (instead of stdout)")

	if len(args) == 0 {
		log.SetPrefix("")
		log.Fatal("Usage: pg fmt [flags] <file>\nFlags:\n\t-w write to file (instead of stdout)")
	}
	in := args[len(args)-1]
	flags.Parse(args[:len(args)-1])

	f, err := os.Open(in)
	if err != nil {
		log.Fatalf("cannot open file: %v", err)
	}
	defer f.Close()

	src, err := ioutil.ReadAll(f)
	if err != nil {
		log.Fatalf("cannot read file: %v", err)
	}

	g, err := parser.Parse(src, in)
	if err != nil {
		log.Fatalf(err.Error())
	}

	if *write {
		f.Close()
		var buf bytes.Buffer
		if err := printer.Fprint(&buf, g); err != nil {
			log.Fatalf("cannot print grammar: %v", err)
		}
		if err = ioutil.WriteFile(in, buf.Bytes(), 0644); err != nil {
			log.Fatalf("cannot write grammar: %v", err)
		}
		return
	}
	if err := printer.Fprint(os.Stdout, g); err != nil {
		log.Fatalf("cannot print grammar: %v", err)
	}
}
Пример #4
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)
}