orangeduck / mpc

A Parser Combinator library for C
Other
2.67k stars 292 forks source link

cant seem to capture a hyphen #85

Closed mgood7123 closed 5 years ago

mgood7123 commented 5 years ago

https://paste.pound-python.org/show/vy90zrfxIKiBVyxAXusz/

#include "../mpc.h"

void eval(char * string, mpc_parser_t *p, mpc_result_t * r) {
    if (mpc_parse("test", string, p, r)) {
      mpc_ast_print((*r).output);
      mpc_ast_delete((*r).output);
    } else {
      mpc_err_print((*r).error);
      mpc_err_delete((*r).error);
    }
}

#define mpcnew(x)   mpc_parser_t * x = mpc_new(#x)

int main(int argc, char **argv) {

  mpcnew(Shell);
  mpcnew(Command);
  mpcnew(Expression);
  mpcnew(Alpha);
  mpcnew(Alnum);
  mpcnew(Digit);
  mpcnew(Dollar);
  mpcnew(At);
  mpcnew(Equals);
  mpcnew(Variable);
  mpcnew(Array);
  mpcnew(Assignment);
  mpcnew(Index);
  mpcnew(Command_End);
  mpcnew(Line);
  mpcnew(Print);
  mpcnew(Args);
  mpcnew(Hyphen);
  mpcnew(Space);
  mpc_parser_t * n = mpc_newline(); mpcnew(nl); mpc_define(nl,n);

  mpca_lang(MPCA_LANG_DEFAULT,
    " Shell      : <Command>+;"
    " Command    : (<Expression> | <Line>) <Command_End> ; "
    " Line       : <Alpha>* | <Hyphen>* | <Space>* ;"
    " Args       : '*';"
    " Hyphen     : '-';"
    " Space      : ' ';"
    " Command_End: ';' | <nl> | /$/; "
    " Expression : <Assignment> | <Variable> | <Array> | <Index>; "
    " Assignment : <Alpha> <Equals> ( <Alnum> | <Variable> | <Array>)?;  "
    " Variable   : <Dollar> ( <At> | <Alnum> ) ;"
    " Array      : <Alpha> <Index> ;"
    " Index      : '[' ( <Digit> | <Array> ) ']' ;"
    " Alpha      : /[a-z]+[A-Z]+/ | /[A-Z]+[a-z]+/ | /[a-z]+/ | /[A-Z]+/;"
    " Alnum      : <Alpha> | <Digit>;"
    " Digit      : /[0-9]+/;"
    " Dollar     : '$' ;"
    " At         : '@' ;"
    " Equals     : '=' ;",
    Shell, Command, Line, Args, Hyphen, Space, Command_End, nl, Expression, Assignment, Variable, Array, Index, Alpha, Alnum, Digit, Dollar, At, Equals, Print, NULL);

  mpc_result_t r;
  eval("a=3; b=9; a=$b; a[b[0]]; azG[6] ;ls def kj hgj yih;bash -", Shell, &r);
  mpc_cleanup(20, Shell, Command, Line, Args, Hyphen, Space, Command_End, nl, Expression, Assignment, Variable, Array, Index, Alpha, Alnum, Digit, Dollar, At, Equals, Print, NULL);

  return 0;

}
mobile_c@Mobile-C:~/git/mpc/examples$ gcc shell.c ../mpc.c && ./a.out> 
  Command|> 
    Expression|Assignment|> 
      Alpha|regex:1:1 'a'
      Equals|char:1:2 '='
      Alnum|Digit|regex:1:3 '3'
    Command_End|char:1:4 ';'
  Command|> 
    Expression|Assignment|> 
      Alpha|regex:1:6 'b'
      Equals|char:1:7 '='
      Alnum|Digit|regex:1:8 '9'
    Command_End|char:1:9 ';'
  Command|> 
    Expression|Assignment|> 
      Alpha|regex:1:11 'a'
      Equals|char:1:12 '='
      Variable|> 
        Dollar|char:1:13 '$'
        Alnum|Alpha|regex:1:14 'b'
    Command_End|char:1:15 ';'
  Command|> 
    Expression|Array|> 
      Alpha|regex:1:17 'a'
      Index|> 
        char:1:18 '['
        Array|> 
          Alpha|regex:1:19 'b'
          Index|> 
            char:1:20 '['
            Digit|regex:1:21 '0'
            char:1:22 ']'
        char:1:23 ']'
    Command_End|char:1:24 ';'
  Command|> 
    Expression|Array|> 
      Alpha|regex:1:26 'azG'
      Index|> 
        char:1:29 '['
        Digit|regex:1:30 '6'
        char:1:31 ']'
    Command_End|char:1:33 ';'
  Command|> 
    Line|> 
      Alpha|regex:1:34 'ls'
      Alpha|regex:1:37 'def'
      Alpha|regex:1:41 'kj'
      Alpha|regex:1:44 'hgj'
      Alpha|regex:1:48 'yih'
    Command_End|char:1:51 ';'
mobile_c@Mobile-C:~/git/mpc/examples$ 

it is however possible to capture it alone (with just the hyphen rule), im not sure why yet https://paste.pound-python.org/show/PUHVGTccAcC6Xw53UAjb/

#include "../mpc.h"

void eval(char * string, mpc_parser_t *p, mpc_result_t * r) {
    if (mpc_parse("test", string, p, r)) {
      mpc_ast_print((*r).output);
      mpc_ast_delete((*r).output);
    } else {
      mpc_err_print((*r).error);
      mpc_err_delete((*r).error);
    }
}

#define mpcnew(x)   mpc_parser_t * x = mpc_new(#x)

int main(int argc, char **argv) {

  mpcnew(Hyphen);

  mpca_lang(MPCA_LANG_DEFAULT,
    " Hyphen     : '-';",
    Hyphen, NULL);

  mpc_result_t r;
  eval("-", Hyphen, &r);
  mpc_cleanup(1, Hyphen, NULL);

  return 0;

}
mobile_c@Mobile-C:~/git/mpc/examples$ gcc shell.c ../mpc.c && ./a.out
char:1:1 '-'
mobile_c@Mobile-C:~/git/mpc/examples$ 
mgood7123 commented 5 years ago

if i do

Line       : <Hyphen> | <Equals> | <Digit>

then i get

test:1:1: error: expected '-', '=' or one or more of one of '0123456789' at 'a'

and if i do

Line       : <Hyphen> | <Equals> | <Digit> | <Alpha>

then i get

test:1:2: error: expected one of 'abcdefghijklmnopqrstuvwxyz', one or more of one of 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', ';', newline or end of input at '='
mgood7123 commented 5 years ago

with

Command    : <Line> <Command_End>
mgood7123 commented 5 years ago

aswell as matching against

  mpc_parser_t * n = mpc_newline(); mpcnew(nl); mpc_define(nl,n);

    " Command    : <Expression> <Command_End> ; "
    " Expression : <Assignment> | <Variable> | <Array> | <Index>; "
    " Assignment : <Alpha> <Equals> ( <Alnum> | <Variable> | <Array>)?;  "
    " Variable   : <Dollar> ( <At> | <Alnum> ) ;"
    " Array      : <Alpha> <Index> ;"
    " Index      : '[' ( <Digit> | <Array> ) ']' ;"
    " Alpha      : /[a-z]+[A-Z]+/ | /[A-Z]+[a-z]+/ | /[a-z]+/ | /[A-Z]+/;"
    " Alnum      : <Alpha> | <Digit>;"
    " Digit      : /[0-9]+/;"
    " Dollar     : '$' ;"
    " At         : '@' ;"
    " Equals     : '=' ;",
    " Command_End: ';' | <nl> | /$/; "

with

a=3\nb=9;

i get

test:2:1: error: expected ';', newline or end of input at 'b'
orangeduck commented 5 years ago

It is hard for me to say exactly what is wrong and how to fix it without knowing what your intent is but in your original grammar I don't think the Hyphen clause can ever be parsed as part of a Line because the Line will always succeed by matching zero or more Alpha first. I.E. Line can be easily matched by the empty string so it will never attempt to parse Hyphen. (See more here.)

Basically you need to work out how to re-structure your grammar probably be factorizing the terms somehow so that your Line rule matches zero or more Things of some kind where the things themselves can either be identifiers, hypens, or spaces.

mgood7123 commented 5 years ago

basically i want Line to match from Alpha to Command_End, accepting all input characters

orangeduck commented 5 years ago

You can try (<Alpha> | <Hyphen> | <Space>)*

mgood7123 commented 5 years ago

ok

mgood7123 commented 5 years ago

it just loads forever lol

mgood7123 commented 5 years ago

wish there was a mpc_ascii or mpc_printable lol

mgood7123 commented 5 years ago

as mpc_any doesnt work

orangeduck commented 5 years ago

Okay well I am going to close this issue and leave you to debug the grammar yourself since I don't think it is a bug or error in the library.

mgood7123 commented 5 years ago
  mpc_parser_t * n = mpc_any(); mpcnew(Any); mpc_define(Any,n);

  mpca_lang(MPCA_LANG_DEFAULT,
    " Any      : <Any>*;",
    Any, NULL);

  mpc_result_t r;
  eval("a=3; b=9; a=$b; a[b[0]]; azG[6] ;ls def kj hgj yih;bash -", Any, &r);
  mpc_cleanup(1, Any, NULL);
mobile_c@Mobile-C:~/git/mpc/examples$ gcc shell.c ../mpc.c && ./a.out
Segmentation fault (core dumped)
mobile_c@Mobile-C:~/git/mpc/examples$