ianh / owl

A parser generator for visibly pushdown languages.
MIT License
746 stars 21 forks source link

Unexpected result when getting string or identifier #13

Closed ghost closed 5 years ago

ghost commented 5 years ago

Given the following text

emit(<"a" ) Calling parsed_string_get(parsed_expr_get(parsed_arg_get(arg).expr).string).string results in a" ) , though a was expected

Given the following grammar:

#using owl.v4 program = stmt* stmt = identifier ['(' arg* ')'] : func identifier '=' expr : assign 'stream' identifier ':' identifier : creates 'tick' identifier : ticks 'move' move : moves arg = '<' expr move = identifier '<' expr : movel expr '>' identifier : mover expr = [ '(' expr ')' ] : parens number : literal identifier : ident string : str .operators prefix '-' : negative .operators infix left '*' : times '/' : divided-by .operators infix left '+' : plus '-' : minus

ianh commented 5 years ago

Thanks for the report! The problem here is treating the string field in struct parsed_string as a normal C string. You have to use the length field to see how many characters long it is. For example, to print a struct parsed_string, you can do:

void print_string(struct parsed_string string)
{
    fwrite(string.string, string.length, 1, stdout);
}

The reason for this pointer + length representation is to allow the parse tree to refer directly to the bytes of input text rather than making copies of each string which include null terminators. I should make this more clear in the documentation.

ianh commented 5 years ago

If it would be convenient, I could also add a version of parsed_string_get that returns a null-terminated string directly. Calling this function would create an extra copy of its string in order to add the null terminator.

ghost commented 5 years ago

Very grateful for such a fast response! Sorry for my misunderstanding!

ghost commented 5 years ago

This function can also be of some use to those who get the same issue


char *get_string(struct parsed_string string)
{
    static char s[100];
    snprintf(s, string.length + 1, "%s", string.string);
    return s;
}