Skip to content

Go support #272

@meme

Description

@meme

Is there any planned support for Go?

Since it is quite similar syntactically to C, I have just modified all that is necessary to use the simple example from Go to illustrate what I envision:

/*!re2c re2c:flags:i = 1; */

/*!max:re2c*/
/*!re2c
    digit  = [0-9];
    number = digit+;
*/

package main

type Cursor struct {
	data []byte
	state int
}

type YYCTYPE byte
type YYMARKERTYPE *Cursor

func YYPEEK(marker YYMARKERTYPE) YYCTYPE {
	return YYCTYPE(marker.data[marker.state])
}

func YYSKIP(marker YYMARKERTYPE) {
	marker.state++
}

func Lex(YYCURSOR YYMARKERTYPE) int {
	/*!re2c
	re2c:define:YYCTYPE = YYCTYPE;
	re2c:yyfill:enable = 0;

	* { return 1 }

	number {
		fmt.Println("number\n")
		return 0
	}
	*/
}

func main() {
	state := &Cursor{
		data:  []byte("1024 ;]"),
		state: 0,
	}

	fmt.Println(Lex(state))
	fmt.Println(Lex(state))
}
re2c --input custom -W example.r2
/* Generated by re2c 1.3 on Sun Mar 22 12:43:56 2020 */

package main

import "fmt"

type Cursor struct {
	data  []byte
	state int
}

type YYCTYPE byte
type YYMARKERTYPE *Cursor

func YYPEEK(marker YYMARKERTYPE) YYCTYPE {
	return YYCTYPE(marker.data[marker.state])
}

func YYSKIP(marker YYMARKERTYPE) {
	marker.state++
}

func Lex(YYCURSOR YYMARKERTYPE) int {

	{
		var yych YYCTYPE
		yych = YYPEEK(YYCURSOR)
		switch yych {
		case '0':
			fallthrough
		case '1':
			fallthrough
		case '2':
			fallthrough
		case '3':
			fallthrough
		case '4':
			fallthrough
		case '5':
			fallthrough
		case '6':
			fallthrough
		case '7':
			fallthrough
		case '8':
			fallthrough
		case '9':
			goto yy4
		default:
			goto yy2
		}
	yy2:
		YYSKIP(YYCURSOR)
		{
			return 1
		}
	yy4:
		YYSKIP(YYCURSOR)
		yych = YYPEEK(YYCURSOR)
		switch yych {
		case '0':
			fallthrough
		case '1':
			fallthrough
		case '2':
			fallthrough
		case '3':
			fallthrough
		case '4':
			fallthrough
		case '5':
			fallthrough
		case '6':
			fallthrough
		case '7':
			fallthrough
		case '8':
			fallthrough
		case '9':
			goto yy4
		default:
			goto yy6
		}
	yy6:
		{
			fmt.Println("number\n")
			return 0
		}
	}

}

func main() {
	state := &Cursor{
		data:  []byte("1024 ;]"),
		state: 0,
	}

	fmt.Println(Lex(state))
	fmt.Println(Lex(state))
}

The patch is as follows (modifications only to what was deemed necessary):

git diff
diff --git a/src/codegen/emit_action.cc b/src/codegen/emit_action.cc
index 3d51707b..be5ec626 100644
--- a/src/codegen/emit_action.cc
+++ b/src/codegen/emit_action.cc
@@ -327,7 +327,7 @@ void gen_goto(code_lines_t &code, const State *from, const State *to
 
     if (to) {
         code.push_back("goto " + opts->labelPrefix
-            + to_string(to->label) + ";\n");
+            + to_string(to->label) + "\n");
     }
 }
 
diff --git a/src/codegen/emit_dfa.cc b/src/codegen/emit_dfa.cc
index b829b534..e41a2b74 100644
--- a/src/codegen/emit_dfa.cc
+++ b/src/codegen/emit_dfa.cc
@@ -229,7 +229,7 @@ void DFA::emit(Output & output, uint32_t& ind, bool isLastCond, bool& bPrologBra
             {
                 if (opts->bEmitYYCh)
                 {
-                    output.wind(ind).wstring(opts->yyctype).ws(" ").wstring(opts->yych).ws(";\n");
+                    output.wind(ind).ws("var ").wstring(opts->yych).ws(" ").wstring(opts->yyctype).ws("\n");
                 }
                 output.wdelay_yyaccept_init (ind);
             }
diff --git a/src/codegen/go_emit.cc b/src/codegen/go_emit.cc
index c608b506..88f5792c 100644
--- a/src/codegen/go_emit.cc
+++ b/src/codegen/go_emit.cc
@@ -61,7 +61,7 @@ void Case::emit (Output & o, uint32_t ind) const
             bool last_case = i == ranges.size () - 1 && b == ranges[i].second - 1;
             if (!last_case)
             {
-                o.ws("\n");
+                o.ws(" fallthrough\n");
             }
         }
     }
@@ -69,7 +69,7 @@ void Case::emit (Output & o, uint32_t ind) const
 
 void Cases::emit(Output &o, uint32_t ind, const DFA &dfa, const State *from) const
 {
-    o.wind(ind).ws("switch (").wstring(o.block().opts->yych).ws(") {\n");
+    o.wind(ind).ws("switch ").wstring(o.block().opts->yych).ws(" {\n");
 
     for (uint32_t i = 1; i < cases_size; ++i) {
         const Case &c = cases[i];
diff --git a/src/codegen/input_api.cc b/src/codegen/input_api.cc
index 6760711d..a4ae5ce9 100644
--- a/src/codegen/input_api.cc
+++ b/src/codegen/input_api.cc
@@ -12,7 +12,7 @@ std::string output_expr_peek(const opt_t *opts)
 {
     return opts->input_api == INPUT_DEFAULT
         ? "*" + opts->yycursor
-        : opts->yypeek + " ()";
+        : opts->yypeek + "(" + opts->yycursor + ")";
 }
 
 std::string output_restore(uint32_t ind, const opt_t *opts)
@@ -47,7 +47,7 @@ void output_peek(std::ostream &o, uint32_t ind, const opt_t *opts)
 {
     o << indent(ind, opts->indString) << opts->yych << " = " << yych_conv(opts);
     if (opts->input_api == INPUT_CUSTOM) {
-        o << opts->yypeek << " ()";
+        o << opts->yypeek << "(" + opts->yycursor + ")";
     } else {
         o << "*" << opts->yycursor;
     }
@@ -58,7 +58,7 @@ void output_skip(std::ostream &o, uint32_t ind, const opt_t *opts)
 {
     o << indent(ind, opts->indString);
     if (opts->input_api == INPUT_CUSTOM) {
-        o << opts->yyskip << " ()";
+        o << opts->yyskip << "(" + opts->yycursor + ")";
     } else {
         o << "++" << opts->yycursor;
     }

I am wondering if you would be open to further work on the Go output, to be used with the -go compiler flag, for example.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions