Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.arch.embedded > #18900 > unrolled thread
| Started by | Don Y <this@is.not.me.com> |
|---|---|
| First post | 2014-10-22 12:14 -0700 |
| Last post | 2014-10-25 21:11 -0400 |
| Articles | 20 on this page of 44 — 12 participants |
Back to article view | Back to comp.arch.embedded
Parsers for extensible grammars? Don Y <this@is.not.me.com> - 2014-10-22 12:14 -0700
Re: Parsers for extensible grammars? Don Y <this@is.not.me.com> - 2014-10-22 12:17 -0700
Re: Parsers for extensible grammars? Tim Wescott <seemywebsite@myfooter.really> - 2014-10-22 15:13 -0500
Re: Parsers for extensible grammars? Don Y <this@is.not.me.com> - 2014-10-22 22:54 -0700
Re: Parsers for extensible grammars? Stefan Reuther <stefan.news@arcor.de> - 2014-10-23 18:36 +0200
Re: Parsers for extensible grammars? Don Y <this@is.not.me.com> - 2014-10-23 12:10 -0700
Re: Parsers for extensible grammars? Tim Wescott <seemywebsite@myfooter.really> - 2014-10-23 13:45 -0500
Re: Parsers for extensible grammars? Don Y <this@is.not.me.com> - 2014-10-23 12:15 -0700
Re: Parsers for extensible grammars? jim.brakefield@ieee.org - 2014-10-24 07:05 -0700
Re: Parsers for extensible grammars? Don Y <this@is.not.me.com> - 2014-10-24 08:04 -0700
Re: Parsers for extensible grammars? Clifford Heath <no.spam@please.net> - 2014-10-23 08:22 +1100
Re: Parsers for extensible grammars? Don Y <this@is.not.me.com> - 2014-10-22 23:25 -0700
Re: Parsers for extensible grammars? George Neuner <gneuner2@comcast.net> - 2014-10-23 04:45 -0400
Re: Parsers for extensible grammars? Don Y <this@is.not.me.com> - 2014-10-23 04:14 -0700
Re: Parsers for extensible grammars? George Neuner <gneuner2@comcast.net> - 2014-10-23 16:49 -0400
Re: Parsers for extensible grammars? Don Y <this@is.not.me.com> - 2014-10-24 07:38 -0700
Re: Parsers for extensible grammars? George Neuner <gneuner2@comcast.net> - 2014-10-26 03:47 -0400
Re: Parsers for extensible grammars? Don Y <this@is.not.me.com> - 2014-10-26 08:41 -0700
Re: Parsers for extensible grammars? George Neuner <gneuner2@comcast.net> - 2014-10-26 14:36 -0400
Re: Parsers for extensible grammars? Don Y <this@is.not.me.com> - 2014-10-26 12:37 -0700
Re: Parsers for extensible grammars? George Neuner <gneuner2@comcast.net> - 2014-10-26 18:54 -0400
Re: Parsers for extensible grammars? Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> - 2014-10-25 02:02 +0000
Re: Parsers for extensible grammars? Don Y <this@is.not.me.com> - 2014-10-25 01:56 -0700
Re: Parsers for extensible grammars? Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> - 2014-10-25 11:15 +0000
Re: Parsers for extensible grammars? Don Y <this@is.not.me.com> - 2014-10-25 10:21 -0700
Re: Parsers for extensible grammars? Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> - 2014-10-26 01:05 +0000
Re: Parsers for extensible grammars? Don Y <this@is.not.me.com> - 2014-10-25 19:37 -0700
Re: Parsers for extensible grammars? Andrew Smallshaw <andrews@sdf.lonestar.org> - 2014-10-23 20:04 +0000
Re: Parsers for extensible grammars? Les Cargill <lcargill99@comcast.com> - 2014-10-23 22:30 -0500
Re: Parsers for extensible grammars? rickman <gnuarm@gmail.com> - 2014-10-25 13:36 -0400
Re: Parsers for extensible grammars? Les Cargill <lcargill99@comcast.com> - 2014-10-25 13:14 -0500
Re: Parsers for extensible grammars? rickman <gnuarm@gmail.com> - 2014-10-25 14:23 -0400
Re: Parsers for extensible grammars? Les Cargill <lcargill99@comcast.com> - 2014-10-26 00:50 -0500
Re: Parsers for extensible grammars? albert@spenarnc.xs4all.nl (Albert van der Horst) - 2014-10-26 19:21 +0000
Re: Parsers for extensible grammars? rickman <gnuarm@gmail.com> - 2014-10-26 15:29 -0400
Re: Parsers for extensible grammars? Paul E Bennett <Paul_E.Bennett@topmail.co.uk> - 2014-10-24 09:56 +0100
Re: Parsers for extensible grammars? Don Y <this@is.not.me.com> - 2014-10-24 07:46 -0700
Re: Parsers for extensible grammars? Don Y <this@is.not.me.com> - 2014-10-25 19:54 -0700
Re: Parsers for extensible grammars? Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> - 2014-10-26 12:15 +0000
Re: Parsers for extensible grammars? Don Y <this@is.not.me.com> - 2014-10-26 09:02 -0700
Re: Parsers for extensible grammars? rickman <gnuarm@gmail.com> - 2014-10-26 12:13 -0400
Re: Parsers for extensible grammars? rickman <gnuarm@gmail.com> - 2014-10-25 13:35 -0400
Re: Parsers for extensible grammars? Paul E Bennett <Paul_E.Bennett@topmail.co.uk> - 2014-10-26 01:29 +0100
Re: Parsers for extensible grammars? rickman <gnuarm@gmail.com> - 2014-10-25 21:11 -0400
Page 1 of 3 [1] 2 3 Next page →
| From | Don Y <this@is.not.me.com> |
|---|---|
| Date | 2014-10-22 12:14 -0700 |
| Subject | Parsers for extensible grammars? |
| Message-ID | <m28vlb$lum$1@speranza.aioe.org> |
Hi, [I probably should direct this at George... :> ] I'm writing a command parser. Some set of commands are "common". But, other instances of the parser are augmented with additional commands/syntax. [These additions are known at compile time, not "dynamic"] Ideally, I want a solution that allows folks developing those "other" commands to just "bolt onto" what I have done. E.g., creating a single "grammar definition" (lex/yacc) is probably not a good way to go (IME, most small parsers tend to be ad hoc). [Note: I can't even guarantee that the extensions will be consistent or "harmonious" with the grammar that I implement] A naive approach (?) might be for my code to take a crack at a particular "statement"/command and, in case of FAIL, invoke some bolt-on parser to give it a chance to make sense out of the input. If *it* FAILs, then the input is invalid, etc. This sounds like an incredible kluge. Any better suggestions?
[toc] | [next] | [standalone]
| From | Don Y <this@is.not.me.com> |
|---|---|
| Date | 2014-10-22 12:17 -0700 |
| Message-ID | <m28vqs$lum$2@speranza.aioe.org> |
| In reply to | #18900 |
On 10/22/2014 12:14 PM, Don Y wrote: > Ideally, I want a solution that allows folks developing those > "other" commands to just "bolt onto" what I have done. E.g., > creating a single "grammar definition" (lex/yacc) is probably > not a good way to go (IME, most small parsers tend to be ad hoc). By that, I mean: having folks augment a lex/yacc grammar definition that I've developed as the basis of these "common" commands is probably ill-advised. *I* can choose such an implementation for the common commands but should probably not impose that solution on the extensions (and risk folks breaking the common stuff!)
[toc] | [prev] | [next] | [standalone]
| From | Tim Wescott <seemywebsite@myfooter.really> |
|---|---|
| Date | 2014-10-22 15:13 -0500 |
| Message-ID | <TZ6dnVdPYcdMktXJnZ2dnUVZ5r-dnZ2d@giganews.com> |
| In reply to | #18900 |
On Wed, 22 Oct 2014 12:14:06 -0700, Don Y wrote: > Hi, > > [I probably should direct this at George... :> ] > > I'm writing a command parser. Some set of commands are "common". > But, other instances of the parser are augmented with additional > commands/syntax. > > [These additions are known at compile time, not "dynamic"] > > Ideally, I want a solution that allows folks developing those "other" > commands to just "bolt onto" what I have done. E.g., creating a single > "grammar definition" (lex/yacc) is probably not a good way to go (IME, > most small parsers tend to be ad hoc). > > [Note: I can't even guarantee that the extensions will be consistent or > "harmonious" with the grammar that I implement] > > A naive approach (?) might be for my code to take a crack at a > particular "statement"/command and, in case of FAIL, invoke some bolt-on > parser to give it a chance to make sense out of the input. If *it* > FAILs, then the input is invalid, etc. > > This sounds like an incredible kluge. Any better suggestions? If it's always something simple like <command> <argument> <argument> <argument> and the only thing that's changing is the command and (possibly) the argument types (text, numerical, etc.) that are bound to it, then a parser should be pretty easy -- I wouldn't even bother with Lex and Yacc. -- Tim Wescott Wescott Design Services http://www.wescottdesign.com
[toc] | [prev] | [next] | [standalone]
| From | Don Y <this@is.not.me.com> |
|---|---|
| Date | 2014-10-22 22:54 -0700 |
| Message-ID | <m2a55m$6po$1@speranza.aioe.org> |
| In reply to | #18903 |
On 10/22/2014 1:13 PM, Tim Wescott wrote:
> On Wed, 22 Oct 2014 12:14:06 -0700, Don Y wrote:
>
>> Hi,
>>
>> [I probably should direct this at George... :> ]
>>
>> I'm writing a command parser. Some set of commands are "common".
>> But, other instances of the parser are augmented with additional
>> commands/syntax.
>>
>> [These additions are known at compile time, not "dynamic"]
>>
>> Ideally, I want a solution that allows folks developing those "other"
>> commands to just "bolt onto" what I have done. E.g., creating a single
>> "grammar definition" (lex/yacc) is probably not a good way to go (IME,
>> most small parsers tend to be ad hoc).
>>
>> [Note: I can't even guarantee that the extensions will be consistent or
>> "harmonious" with the grammar that I implement]
>>
>> A naive approach (?) might be for my code to take a crack at a
>> particular "statement"/command and, in case of FAIL, invoke some bolt-on
>> parser to give it a chance to make sense out of the input. If *it*
>> FAILs, then the input is invalid, etc.
>>
>> This sounds like an incredible kluge. Any better suggestions?
>
> If it's always something simple like
>
> <command> <argument> <argument> <argument>
>
> and the only thing that's changing is the command and (possibly) the
> argument types (text, numerical, etc.) that are bound to it, then a parser
> should be pretty easy -- I wouldn't even bother with Lex and Yacc.
The problem I'm stuck with is not knowing what is likely to be added.
While I suspect most will be similarly trivial, I can also imagine
some esoteric additions!
The "common" commands are trivial enough that, if I knew ALL would be
of similar form, I would almost adopt an approach of sequentially
attempting to parse a command with individual templates -- until one
"fit". Extensions would just be tacked onto the end of a (short) series
of conditionals:
if (parse(string, template1))
command1();
else if (parse(string, template2))
command2();
else if ...
Performance isn't an issue (though footprint may be). This would allow
extensions to *simply* focus on what they needed to do for *those*
individual commands (without fear of extensions mucking up the common
commands!)
I wouldn't run the risk of someone buggering a "shared grammar" definition
(and failing to add appropriate regression tests to detect that).
But, if the extensions get more esoteric (than this trivial approach),
this starts to look toy-ish; there's very little to *leverage*, here... :<
[toc] | [prev] | [next] | [standalone]
| From | Stefan Reuther <stefan.news@arcor.de> |
|---|---|
| Date | 2014-10-23 18:36 +0200 |
| Message-ID | <m2bhqo.1a4.1@stefan.msgid.phost.de> |
| In reply to | #18910 |
Don Y wrote:
> On 10/22/2014 1:13 PM, Tim Wescott wrote:
>> If it's always something simple like
>>
>> <command> <argument> <argument> <argument>
>>
>> and the only thing that's changing is the command and (possibly) the
>> argument types (text, numerical, etc.) that are bound to it, then a
>> parser
>> should be pretty easy -- I wouldn't even bother with Lex and Yacc.
>
> The problem I'm stuck with is not knowing what is likely to be added.
> While I suspect most will be similarly trivial, I can also imagine
> some esoteric additions!
You could try to bring every command into the <command> <argument>...
form with some clever syntax. I'm tempted to say "Lisp", but that
probably doesn't enjoy universal love :-) However, you can easily bring
if (foo) { bar(); baz(); } else { fred(); }
into "<command> <argument>..." form by making "{}" string delimiters.
This makes this a command 'if' with four parameters: an expression
'(foo)', a string for the 'if' command, an unquoted word 'else', and a
string for the 'else' command.
I recently built a command shell like that, and I believe Tcl does it
the same way. So all you would need to give your users would be a
possiblity to register a command verb, and a way to evaluate strings as
command sequences.
Stefan
[toc] | [prev] | [next] | [standalone]
| From | Don Y <this@is.not.me.com> |
|---|---|
| Date | 2014-10-23 12:10 -0700 |
| Message-ID | <m2bjq6$tpt$1@speranza.aioe.org> |
| In reply to | #18918 |
On 10/23/2014 9:36 AM, Stefan Reuther wrote:
> Don Y wrote:
>> On 10/22/2014 1:13 PM, Tim Wescott wrote:
>>> If it's always something simple like
>>>
>>> <command> <argument> <argument> <argument>
>>>
>>> and the only thing that's changing is the command and (possibly) the
>>> argument types (text, numerical, etc.) that are bound to it, then a
>>> parser
>>> should be pretty easy -- I wouldn't even bother with Lex and Yacc.
>>
>> The problem I'm stuck with is not knowing what is likely to be added.
>> While I suspect most will be similarly trivial, I can also imagine
>> some esoteric additions!
>
> You could try to bring every command into the <command> <argument>...
> form with some clever syntax. I'm tempted to say "Lisp", but that
> probably doesn't enjoy universal love :-) However, you can easily bring
> if (foo) { bar(); baz(); } else { fred(); }
> into "<command> <argument>..." form by making "{}" string delimiters.
> This makes this a command 'if' with four parameters: an expression
> '(foo)', a string for the 'if' command, an unquoted word 'else', and a
> string for the 'else' command.
Note the (contrived) example I posted (elsewhere this thread) attempts
to do that -- by decomposing what might otherwise be "complex" (multivalued)
commands into a series of trivial (single parameter) commands.
E.g., easier to accept an 8 digit HEX value for an IP address (and another
for a mask) than to accept four dotted decimal values (for each).
But, I can't assume others will take a similar approach. Nor can I
imagine the variety of things that they might need/want to address via
this interface.
(sigh)
> I recently built a command shell like that, and I believe Tcl does it
> the same way. So all you would need to give your users would be a
> possiblity to register a command verb, and a way to evaluate strings as
> command sequences.
I suspect I will end up with a set of routines that parse specific types
of tokens (number, hex number, word, etc.) that the DEVELOPER could call
upon in fashioning an ad hoc parser. Perhaps I'm too jaded but I bet
that's how additions will end up being implemented -- past observations
suggest this.
I think it's probably easier for folks to think in terms of: "OK, now I'll
expect an integer in the range of XXX to YYY". Rather than let them
naively do something like read the characters into a fixed size buffer
(buffer overrun potential!), I can handle SAFELY scanning the next token
AS AN INTEGER and report a value that they can just test (plus an error
code if the token isn't an integer).
That, at least, gives something that can be leveraged safely.
[toc] | [prev] | [next] | [standalone]
| From | Tim Wescott <seemywebsite@myfooter.really> |
|---|---|
| Date | 2014-10-23 13:45 -0500 |
| Message-ID | <sPydnUuaKdBH0dTJnZ2dnUU7-VmdnZ2d@giganews.com> |
| In reply to | #18910 |
On Wed, 22 Oct 2014 22:54:13 -0700, Don Y wrote: > On 10/22/2014 1:13 PM, Tim Wescott wrote: >> On Wed, 22 Oct 2014 12:14:06 -0700, Don Y wrote: >> >>> Hi, >>> >>> [I probably should direct this at George... :> ] >>> >>> I'm writing a command parser. Some set of commands are "common". >>> But, other instances of the parser are augmented with additional >>> commands/syntax. >>> >>> [These additions are known at compile time, not "dynamic"] >>> >>> Ideally, I want a solution that allows folks developing those "other" >>> commands to just "bolt onto" what I have done. E.g., creating a >>> single "grammar definition" (lex/yacc) is probably not a good way to >>> go (IME, most small parsers tend to be ad hoc). >>> >>> [Note: I can't even guarantee that the extensions will be consistent >>> or "harmonious" with the grammar that I implement] >>> >>> A naive approach (?) might be for my code to take a crack at a >>> particular "statement"/command and, in case of FAIL, invoke some >>> bolt-on parser to give it a chance to make sense out of the input. If >>> *it* FAILs, then the input is invalid, etc. >>> >>> This sounds like an incredible kluge. Any better suggestions? >> >> If it's always something simple like >> >> <command> <argument> <argument> <argument> >> >> and the only thing that's changing is the command and (possibly) the >> argument types (text, numerical, etc.) that are bound to it, then a >> parser should be pretty easy -- I wouldn't even bother with Lex and >> Yacc. > > The problem I'm stuck with is not knowing what is likely to be added. > While I suspect most will be similarly trivial, I can also imagine some > esoteric additions! Who's going to be adding stuff, why, and why won't you have control over the process? > The "common" commands are trivial enough that, if I knew ALL would be of > similar form, I would almost adopt an approach of sequentially > attempting to parse a command with individual templates -- until one > "fit". Extensions would just be tacked onto the end of a (short) series > of conditionals: > > if (parse(string, template1)) > command1(); > else if (parse(string, template2)) > command2(); > else if ... I have an in-house parser that I use for debugging and service on a number of projects. It's OO in C++, but it basically supports a syntax of <keyword> <anything else> You create an object and give it the keyword, which automagically registers it with the first-layer parser. When someone types something in the first-layer parser looks for the keyword, and if its found, hands it to the object for further parsing. It's crude but effective. I keep telling myself that I'll make more library-ish functionality for parsing the <anything else> bit, but so far that's all ad-hoc. -- Tim Wescott Wescott Design Services http://www.wescottdesign.com
[toc] | [prev] | [next] | [standalone]
| From | Don Y <this@is.not.me.com> |
|---|---|
| Date | 2014-10-23 12:15 -0700 |
| Message-ID | <m2bk4s$v2i$1@speranza.aioe.org> |
| In reply to | #18919 |
On 10/23/2014 11:45 AM, Tim Wescott wrote: > On Wed, 22 Oct 2014 22:54:13 -0700, Don Y wrote: >>>> Ideally, I want a solution that allows folks developing those "other" >>>> commands to just "bolt onto" what I have done. E.g., creating a >>>> single "grammar definition" (lex/yacc) is probably not a good way to >>>> go (IME, most small parsers tend to be ad hoc). >>>> >>>> [Note: I can't even guarantee that the extensions will be consistent >>>> or "harmonious" with the grammar that I implement] >> The problem I'm stuck with is not knowing what is likely to be added. >> While I suspect most will be similarly trivial, I can also imagine some >> esoteric additions! > > Who's going to be adding stuff, why, and why won't you have control over > the process? Other developers. To address the needs of their environments. Because its not my codebase. >> The "common" commands are trivial enough that, if I knew ALL would be of >> similar form, I would almost adopt an approach of sequentially >> attempting to parse a command with individual templates -- until one >> "fit". Extensions would just be tacked onto the end of a (short) series >> of conditionals: >> >> if (parse(string, template1)) >> command1(); >> else if (parse(string, template2)) >> command2(); >> else if ... > > I have an in-house parser that I use for debugging and service on a number > of projects. It's OO in C++, but it basically supports a syntax of > > <keyword> <anything else> > > You create an object and give it the keyword, which automagically > registers it with the first-layer parser. When someone types something in > the first-layer parser looks for the keyword, and if its found, hands it > to the object for further parsing. > > It's crude but effective. I keep telling myself that I'll make more > library-ish functionality for parsing the <anything else> bit, but so far > that's all ad-hoc. I actually think a viable solution might be as above. I.e., write something that parses for *just* one particular command. If no match, try invoking the thing that parses for the *next* particular command. Lather, rinse, repeat until a match is found (successful parse) *or* no more possibilities (FAIL). Again, this gets used with very low frequency so it doesn't have to be super efficient. With subroutines/functions that the developer can invoke (because I had to write them to parse the commands that *I* implemented), it could be just a few lines of code extracting parameters from syntactic sugar, etc. I *don't* want to intimidate a developer into having to embrace some more formal framework with which he may not be comfortable. That way lies bugs.
[toc] | [prev] | [next] | [standalone]
| From | jim.brakefield@ieee.org |
|---|---|
| Date | 2014-10-24 07:05 -0700 |
| Message-ID | <730d49fb-a52a-429e-8371-0b623ab015be@googlegroups.com> |
| In reply to | #18910 |
On Thursday, October 23, 2014 12:54:03 AM UTC-5, Don Y wrote: > On 10/22/2014 1:13 PM, Tim Wescott wrote: > > On Wed, 22 Oct 2014 12:14:06 -0700, Don Y wrote: > > The problem I'm stuck with is not knowing what is likely to be added. > While I suspect most will be similarly trivial, I can also imagine > some esoteric additions! > Once upon a time, realized that if one uses distinct left and right operator precedence values one can include brackets as operators (high outside precedence and matching low inside precedence). Never figured out how to parse an operator that had simultaneous infix, prefix and suffix versions. The appeal is that the parser is table driven and that the table is simple and easy to amend. Am told that this approach has limitations and has been tried.
[toc] | [prev] | [next] | [standalone]
| From | Don Y <this@is.not.me.com> |
|---|---|
| Date | 2014-10-24 08:04 -0700 |
| Message-ID | <m2dpp1$kmv$1@speranza.aioe.org> |
| In reply to | #18933 |
On 10/24/2014 7:05 AM, jim.brakefield@ieee.org wrote: > On Thursday, October 23, 2014 12:54:03 AM UTC-5, Don Y wrote: >> On 10/22/2014 1:13 PM, Tim Wescott wrote: >>> On Wed, 22 Oct 2014 12:14:06 -0700, Don Y wrote: >> >> The problem I'm stuck with is not knowing what is likely to be added. >> While I suspect most will be similarly trivial, I can also imagine some >> esoteric additions! >> > Once upon a time, realized that if one uses distinct left and right operator > precedence values one can include brackets as operators (high outside > precedence and matching low inside precedence). Never figured out how to > parse an operator that had simultaneous infix, prefix and suffix versions. > The appeal is that the parser is table driven and that the table is simple > and easy to amend. Am told that this approach has limitations and has been > tried. The ideal would be to write a usage() for each command -- to be displayed when "help" is invoked. Then, algorithmically extract the parse information from the example syntax present in that usage() presentation. But, I think that's too lofty a goal. It would, by necessity, make the usage() very verbose -- to qualify all the restrictions on the tokens in the example syntax (unless the code was smart enough to recognize common constructs and document them elsewhere). "Small" tends to preclude much of that added smarts.
[toc] | [prev] | [next] | [standalone]
| From | Clifford Heath <no.spam@please.net> |
|---|---|
| Date | 2014-10-23 08:22 +1100 |
| Message-ID | <dcV1w.320229$Hb3.258607@fx03.iad> |
| In reply to | #18900 |
On 23/10/14 06:14, Don Y wrote: > I'm writing a command parser. Some set of commands are "common". > But, other instances of the parser are augmented with additional > commands/syntax. > > [These additions are known at compile time, not "dynamic"] > > Ideally, I want a solution that allows folks developing those > "other" commands to just "bolt onto" what I have done. E.g., > creating a single "grammar definition" (lex/yacc) is probably > not a good way to go (IME, most small parsers tend to be ad hoc). > > [Note: I can't even guarantee that the extensions will be > consistent or "harmonious" with the grammar that I implement] > > A naive approach (?) might be for my code to take a crack at > a particular "statement"/command and, in case of FAIL, invoke > some bolt-on parser to give it a chance to make sense out of > the input. If *it* FAILs, then the input is invalid, etc. > > This sounds like an incredible kluge. Any better suggestions? You want composable grammars. This is right in a core area of my expertise. Lex/Yacc (and all other forms of bottom-up LR parsing) are the wrong way to go, because the tools must do deep analysis of the entire grammar before producing a parser, and the errors that occur require significant expertise to understand. Top-down parsers (also known as LL or recursive descent) are much easier to write and debug. They're typically implemented using limited look-ahead (often one token, LL-1) and are slightly less powerful than LR parsers with the same look-ahead. When an LL parser has unlimited lookahead, they're very powerful but can have horrible performance due to the extensive backtracking required. However, so-called packrat parsers trade memory for performance, while retaining almost all the power of unlimited backtracking. For a grammar of N rules, the memory usage for an input of size M is O(N*M), that is, linear in the size of the input. Because the CPU performance is so good,there's no need for a separate lexer - the parse performance is the same as the DFAs used for lexing so there's no advantage to be had. Packrat parsers are generally created from PEGs (Parsing Expression Grammars). There are plenty of PEG parser generators; I maintain the most widely used one for Ruby, but they exist for dozens of languages. The really nice thing about LL parsers is they're composable. You can take two grammars with different rules, and simply layer one on top of the other. Often it's helpful to allow a rule in one grammar to call the same rule (by name) in the other grammar - this works very like O-O inheritance. Note that none of this will help you if you want "minimum abbreviation" support for your keywords. That is best implemented using a trie. It's all compatible with the use of a PEG parser though; the keyword matcher won't be written using a PEG, is all. Clifford Heath.
[toc] | [prev] | [next] | [standalone]
| From | Don Y <this@is.not.me.com> |
|---|---|
| Date | 2014-10-22 23:25 -0700 |
| Message-ID | <m2a6vl$act$1@speranza.aioe.org> |
| In reply to | #18905 |
On 10/22/2014 2:22 PM, Clifford Heath wrote: > On 23/10/14 06:14, Don Y wrote: >> I'm writing a command parser. Some set of commands are "common". >> But, other instances of the parser are augmented with additional >> commands/syntax. >> >> [These additions are known at compile time, not "dynamic"] >> >> Ideally, I want a solution that allows folks developing those >> "other" commands to just "bolt onto" what I have done. E.g., >> creating a single "grammar definition" (lex/yacc) is probably >> not a good way to go (IME, most small parsers tend to be ad hoc). >> >> [Note: I can't even guarantee that the extensions will be >> consistent or "harmonious" with the grammar that I implement] > You want composable grammars. This is right in a core area of my expertise. > Lex/Yacc (and all other forms of bottom-up LR parsing) are the wrong way to go, > because the tools must do deep analysis of the entire grammar before producing > a parser, and the errors that occur require significant expertise to understand. > > Top-down parsers (also known as LL or recursive descent) are much easier to > write and debug. They're typically implemented using limited look-ahead (often > one token, LL-1) and are slightly less powerful than LR parsers with the same > look-ahead. > > When an LL parser has unlimited lookahead, they're very powerful but can have > horrible performance due to the extensive backtracking required. > > However, so-called packrat parsers trade memory for performance, while > retaining almost all the power of unlimited backtracking. For a grammar of N > rules, the memory usage for an input of size M is O(N*M), that is, linear in > the size of the input. Because the CPU performance is so good,there's no need > for a separate lexer - the parse performance is the same as the DFAs used for > lexing so there's no advantage to be had. > > Packrat parsers are generally created from PEGs (Parsing Expression Grammars). > There are plenty of PEG parser generators; I maintain the most widely used one > for Ruby, but they exist for dozens of languages. > > The really nice thing about LL parsers is they're composable. You can take two > grammars with different rules, and simply layer one on top of the other. Often > it's helpful to allow a rule in one grammar to call the same rule (by name) in > the other grammar - this works very like O-O inheritance. > > Note that none of this will help you if you want "minimum abbreviation" support > for your keywords. That is best implemented using a trie. It's all compatible > with the use of a PEG parser though; the keyword matcher won't be written using > a PEG, is all. This sounds like an *ideal* approach! But... I'm concerned that too many folks would find a "formal" grammar tool to be intimidating. I'm thinking about the *hundreds* of different "configuration files" I've encountered, "argument handling", etc. and how *few* of these were implemented with any sort of formal tools. Rather, almost as a RULE, they all seemed to be jumbles of spaghetti code (though they "got the job done", more or less). Cases where "space" was accepted as whitespace -- but "tab", not. Or, vice versa. Cases where comments HAD to begin in column one and others where leading whitespace was ignored. Or, where comments could not coexist with preceding "content" on the same line. Or, where groups of statements had to be co-located on the same line (with some formal delimiter) instead of being allowed to span lines (couple this with a maximum line length constraint and you can see one potential issue!) And, in each case, no compelling REASON for the restrictions (as if "it was too much work" to provide a cleaner/more consistent implementation). I'm left with the impression that these folks either underestimated the complexity of the tasks they set out for themselves; or, were intimidated by more "structured" approaches to SUCH A COMMON PROBLEM! [Or, the structured approaches were harder to comprehend/debug than the ad hoc spaghetti-code implementations!] So, I figure decoupling my portion of the implementation (common commands) from these potential extensions might be A Wise Choice.
[toc] | [prev] | [next] | [standalone]
| From | George Neuner <gneuner2@comcast.net> |
|---|---|
| Date | 2014-10-23 04:45 -0400 |
| Message-ID | <ki7h4atruavqscoelr69o3bkm8ubcrjp5i@4ax.com> |
| In reply to | #18905 |
On Thu, 23 Oct 2014 08:22:24 +1100, Clifford Heath
<no.spam@please.net> wrote:
>On 23/10/14 06:14, Don Y wrote:
>> I'm writing a command parser. Some set of commands are "common".
>> But, other instances of the parser are augmented with additional
>> commands/syntax.
>>
>> [These additions are known at compile time, not "dynamic"]
>>
>> Ideally, I want a solution that allows folks developing those
>> "other" commands to just "bolt onto" what I have done. E.g.,
>> creating a single "grammar definition" (lex/yacc) is probably
>> not a good way to go (IME, most small parsers tend to be ad hoc).
>>
>> [Note: I can't even guarantee that the extensions will be
>> consistent or "harmonious" with the grammar that I implement]
>>
>> A naive approach (?) might be for my code to take a crack at
>> a particular "statement"/command and, in case of FAIL, invoke
>> some bolt-on parser to give it a chance to make sense out of
>> the input. If *it* FAILs, then the input is invalid, etc.
>>
>> This sounds like an incredible kluge. Any better suggestions?
>
>You want composable grammars.
Or just parallel parsers.
Don said "bolt onto" and "harmonious", but it isn't clear to me
whether what he wants is to provide some kind of macro facility in
which new commands are fully expressible in *his* language, or whether
he wants to allow development of a parallel language that remains
interoperable with his but also is separate from it.
The first is [relatively] easy, the second not so much.
In either case, the additional parser should get the first crack at
input with Don's own parser as a fallback.
>Top-down parsers (also known as LL or recursive descent) are much easier
>to write and debug. They're typically implemented using limited
>look-ahead (often one token, LL-1) and are slightly less powerful than
>LR parsers with the same look-ahead.
^^^^^^^^
You mean _much_ less powerful. AFAIK, LR has not been shown to be a
proper superset of LL, but it is known to be a vastly larger space.
The LR(1) subset provably contains LL(1) and also many LL(>1)
languages.
That said, a large number of useful languages can be expressed in LL
with computationally reasonable lookahead. And it is true in general
that LL parsers are easier to understand and debug.
>When an LL parser has unlimited lookahead, they're very powerful but can
>have horrible performance due to the extensive backtracking required.
Not really. "Ungetting" tokens - even a large number of them - is not
very costly as long as 1) trying a parse produces no side effects
[i.e. the predication is purely syntactic], or 2) side effects are
implemented "functionally" and can be simply thrown away.
Syntactic predication and quite a lot of useful semantic predication
can be implemented using stack or region allocation strategies, but
there are some hard spaghetti cases where it's nice to have GC
available in your development language.
>However, so-called packrat parsers trade memory for performance, while
>retaining almost all the power of unlimited backtracking. For a grammar
>of N rules, the memory usage for an input of size M is O(N*M), that is,
>linear in the size of the input. Because the CPU performance is so
>good,there's no need for a separate lexer - the parse performance is the
>same as the DFAs used for lexing so there's no advantage to be had.
>
>Packrat parsers are generally created from PEGs (Parsing Expression
>Grammars). There are plenty of PEG parser generators; I maintain the
>most widely used one for Ruby, but they exist for dozens of languages.
PEG (and GLR also) replicates the parser state to deal with ambiguous
input by following the different paths independently. But the fact is
that most language constructs are unambiguous and thus do not cause
forking, and *unavoidable* ambiguity in the language tends to be
resolved quickly when the ambiguous constructs actually are used.
The problem with PEG (and GLR also) grammars is that there still are
no really useful tools for finding/debugging *unintended* ambiguity.
The generator tool won't give reduce/reduce errors ... warnings maybe,
but not errors ... and will create a parser that just forks on
ambiguous input, wanders off into the hills and gets lost.
Most useful program/control languages do not need PEG (or even GLR).
If your language really is that complicated, you probably should
rethink it.
>The really nice thing about LL parsers is they're composable. You can
>take two grammars with different rules, and simply layer one on top of
>the other. Often it's helpful to allow a rule in one grammar to call the
>same rule (by name) in the other grammar - this works very like O-O
>inheritance.
Yes.
>Note that none of this will help you if you want "minimum abbreviation"
>support for your keywords. That is best implemented using a trie. It's
>all compatible with the use of a PEG parser though; the keyword matcher
>won't be written using a PEG, is all.
The trie would be part of the tokenizer, so it would be compatible
with any parse strategy.
>Clifford Heath.
George
[toc] | [prev] | [next] | [standalone]
| From | Don Y <this@is.not.me.com> |
|---|---|
| Date | 2014-10-23 04:14 -0700 |
| Message-ID | <m2anti$mp3$1@speranza.aioe.org> |
| In reply to | #18913 |
Hi George,
On 10/23/2014 1:45 AM, George Neuner wrote:
> Or just parallel parsers.
>
> Don said "bolt onto" and "harmonious", but it isn't clear to me
> whether what he wants is to provide some kind of macro facility in
> which new commands are fully expressible in *his* language, or whether
> he wants to allow development of a parallel language that remains
> interoperable with his but also is separate from it.
I hadn't considered the idea of expressing "new" commands in terms
of "old"/common commands.
What I am looking for is the ability to define a set of commands
that will "always" be used/useful. Then, allow others to add
to that set of commands to address specific needs that are
necessary/unique to their environment. (i.e., the environment
in which these common commands are deployed)
Contrived example:
MESSAGE <text>
PAUSE <delay>
STDIN <device>
STDOUT <device>
Deploy this in a context where stdin/stdout might want to also support
a serial port ("<device> = TTY") would probably necessitate adding:
BITRATE <speed>
CHARACTER <width>
PARITY <odd/even/off/ignore>
In the presence of multiple TTY's, it might then require:
PORT <address>
IRQ <number>
Deploy it where stdin/stdout are a VDT and, perhaps:
BACKGROUND <color>
FOREGROUND <color>
CURSOR <blink/solid/off>
Deploy it where stdin/stdout are a telnet connection, and perhaps:
IP <address>
MASK <dotted_quad>
GATEWAY <address>
I.e., the "arguments" can't be easily foreseen from the perspective
of the first/common commands.
Note that I've presented these in a somewhat "harmonious"/consistent
manner. Another implementer could have adopted a syntax like:
FORMAT <bitrate><parity><width>
Or:
display WHITE on field of BLUE
Or:
SET IP X.X.X.X/24 VIA Y.Y.Y.Y
I.e., I can't assume he'll consider the <setting> <value> form to be
appropriate to his/her future needs.
> The first is [relatively] easy, the second not so much.
>
> In either case, the additional parser should get the first crack at
> input with Don's own parser as a fallback.
Hmmm... I had considered the opposite approach: let me verify the
input is/isn't a "common command" before exposing the input to the
"other" parser. The thought being: common commands are then
implicitly invariant (you can't change the syntax of them) AND
they "always work" (even if the additional parser has bugs in its
implementation).
[toc] | [prev] | [next] | [standalone]
| From | George Neuner <gneuner2@comcast.net> |
|---|---|
| Date | 2014-10-23 16:49 -0400 |
| Message-ID | <kqji4a9q0093ifp2bmk8lukbk9d2efc1j4@4ax.com> |
| In reply to | #18915 |
Hi Don, On Thu, 23 Oct 2014 04:14:09 -0700, Don Y <this@is.not.me.com> wrote: >On 10/23/2014 1:45 AM, George Neuner wrote: > >> Or just parallel parsers. >> >> Don said "bolt onto" and "harmonious", but it isn't clear to me >> whether what he wants is to provide some kind of macro facility in >> which new commands are fully expressible in *his* language, or whether >> he wants to allow development of a parallel language that remains >> interoperable with his but also is separate from it. > >I hadn't considered the idea of expressing "new" commands in terms >of "old"/common commands. You and I have talked about this before: it doesn't really matter how simple the interface - the way to think about it is as if you are creating a scripting language in which "operators" are the control functions exposed by the device. >What I am looking for is the ability to define a set of commands >that will "always" be used/useful. Then, allow others to add >to that set of commands to address specific needs that are >necessary/unique to their environment. (i.e., the environment >in which these common commands are deployed) > >Contrived example: > > : > >I.e., the "arguments" can't be easily foreseen from the perspective >of the first/common commands. The problem is, that also means the complete set of *functionality* can't be foreseen ... else you would have provided for it already. Your "core" can be operated with it's provided command set, but you can't easily provide for new commands targeting an environment you know nothing about. You may want to look up our (ancient) exchange about runtime parser generators. You don't need that here, but the discussion about providing for JIT generated code to link to your device API is relevant. >> In either case, the additional parser should get the first crack at >> input with Don's own parser as a fallback. > >Hmmm... I had considered the opposite approach: let me verify the >input is/isn't a "common command" before exposing the input to the >"other" parser. The thought being: common commands are then >implicitly invariant (you can't change the syntax of them) AND >they "always work" (even if the additional parser has bugs in its >implementation). You don't want to "front end" the extensions ... if one of your commands is redefined, it won't work if you grab it first. George
[toc] | [prev] | [next] | [standalone]
| From | Don Y <this@is.not.me.com> |
|---|---|
| Date | 2014-10-24 07:38 -0700 |
| Message-ID | <m2do89$hh6$1@speranza.aioe.org> |
| In reply to | #18926 |
Hi George,
On 10/23/2014 1:49 PM, George Neuner wrote:
> On Thu, 23 Oct 2014 04:14:09 -0700, Don Y <this@is.not.me.com> wrote:
>> What I am looking for is the ability to define a set of commands
>> that will "always" be used/useful. Then, allow others to add
>> to that set of commands to address specific needs that are
>> necessary/unique to their environment. (i.e., the environment
>> in which these common commands are deployed)
>>
>> Contrived example:
>>
>> :
>>
>> I.e., the "arguments" can't be easily foreseen from the perspective
>> of the first/common commands.
>
> The problem is, that also means the complete set of *functionality*
> can't be foreseen ... else you would have provided for it already.
Exactly. Because I can't anticipate the functionality that will
be needed in the future. E.g., the contrived example.
> Your "core" can be operated with it's provided command set, but you
> can't easily provide for new commands targeting an environment you
> know nothing about.
Yes. And, I can't "guess" to the types of data/actions that may
need to be "encoded" in that command set.
Nor can I ensure the next guy will have the same approach to the
problem -- half the commands may "feel like mine" while the other
half "feel like his/hers". And, neither group "feels consistent"
with the other.
Like me using infix operators and he using RPN.
> You may want to look up our (ancient) exchange about runtime parser
> generators. You don't need that here, but the discussion about
> providing for JIT generated code to link to your device API is
> relevant.
Can't. The (forced) "computer upgrade" cost me my mail archive
(I don't leave mail stored on server :< )
>>> In either case, the additional parser should get the first crack at
>>> input with Don's own parser as a fallback.
>>
>> Hmmm... I had considered the opposite approach: let me verify the
>> input is/isn't a "common command" before exposing the input to the
>> "other" parser. The thought being: common commands are then
>> implicitly invariant (you can't change the syntax of them) AND
>> they "always work" (even if the additional parser has bugs in its
>> implementation).
>
> You don't want to "front end" the extensions ... if one of your
> commands is redefined, it won't work if you grab it first.
That was exactly the point: that the common commands are *common*
and always behave exactly the same. (as well as "always working"
regardless of how much the other guy mucks with the interface).
E.g., if "run" was a common command and he wanted to "overload"
it to add/alter functionality, he'd have to create a new command
("walk_very_very_quickly") to bind to the actions he desires.
Perhaps he wants to turn on a big red light prior to activating
the mechanism ("run"-ing). If I let him redefine "run" to do this,
I risk him forgetting to verify safety mechanisms are in place
(which other users would ASSUME when invoking "run").
It's a tough call -- assume competence in EVERYTHING? Or, just
assume competence in their knowledge of their "extensions"??
[toc] | [prev] | [next] | [standalone]
| From | George Neuner <gneuner2@comcast.net> |
|---|---|
| Date | 2014-10-26 03:47 -0400 |
| Message-ID | <6q0p4a9mtlm47q9oihbvadobrt43v03eb9@4ax.com> |
| In reply to | #18934 |
On Fri, 24 Oct 2014 07:38:12 -0700, Don Y <this@is.not.me.com> wrote: >On 10/23/2014 1:49 PM, George Neuner wrote: > >> Your "core" can be operated with it's provided command set, but you >> can't easily provide for new commands targeting an environment you >> know nothing about. > >Yes. And, I can't "guess" to the types of data/actions that may >need to be "encoded" in that command set. > >Nor can I ensure the next guy will have the same approach to the >problem -- half the commands may "feel like mine" while the other >half "feel like his/hers". And, neither group "feels consistent" >with the other. I like Simon's idea re: DCL. I only used VMS briefly in school and I wasn't aware that DCL could be extended in that way. It's a nice way to regularize at least the argument input. If all you want is to regularize input, another way might be to borrow from the HTML fast-cgi interface. It doesn't guarantee anything about interoperability per se, but it does arrange that programs get their arguments in recognizable key:value pairs. >The (forced) "computer upgrade" cost me my mail archive >(I don't leave mail stored on server :< ) Ouch. I don't leave anything on provider servers either, but my own IMAP server is backed up regularly. What I was thinking about is less important given compile time parser generation ... we were talking about providing API object and entry point addresses to runtime generated code. The relevance (if any) depends on whether you want to allow grammar extensions direct access to your device API: i.e. whether the extensions should be allowed to manipulate your (part of the) device or whether they have to go through your provided language to do it. >>>> In either case, the additional parser should get the first crack at >>>> input with Don's own parser as a fallback. >>> >>> Hmmm... I had considered the opposite approach: let me verify the >>> input is/isn't a "common command" before exposing the input to the >>> "other" parser. The thought being: common commands are then >>> implicitly invariant (you can't change the syntax of them) AND >>> they "always work" (even if the additional parser has bugs in its >>> implementation). >> >> You don't want to "front end" the extensions ... if one of your >> commands is redefined, it won't work if you grab it first. > >That was exactly the point: that the common commands are *common* >and always behave exactly the same. (as well as "always working" >regardless of how much the other guy mucks with the interface). That's the safe approach, but it's not terribly friendly ... particularly in the case of a reusable component where you don't have any say in the use. A new developer may want to completely change the approach to the command set. >It's a tough call -- assume competence in EVERYTHING? Or, just >assume competence in their knowledge of their "extensions"?? It's reasonable to expect that many developers will have little experience with _formal_ parsing methods and tools ... quite a lot of applications can get by with RegEx or even just separator tokenization and have no need of any formal grammar. George
[toc] | [prev] | [next] | [standalone]
| From | Don Y <this@is.not.me.com> |
|---|---|
| Date | 2014-10-26 08:41 -0700 |
| Message-ID | <m2j4nl$rtn$1@speranza.aioe.org> |
| In reply to | #18959 |
Hi George, On 10/26/2014 12:47 AM, George Neuner wrote: > On Fri, 24 Oct 2014 07:38:12 -0700, Don Y <this@is.not.me.com> wrote: >> On 10/23/2014 1:49 PM, George Neuner wrote: >> >>> Your "core" can be operated with it's provided command set, but you >>> can't easily provide for new commands targeting an environment you >>> know nothing about. >> >> Yes. And, I can't "guess" to the types of data/actions that may >> need to be "encoded" in that command set. >> >> Nor can I ensure the next guy will have the same approach to the >> problem -- half the commands may "feel like mine" while the other >> half "feel like his/hers". And, neither group "feels consistent" >> with the other. > > I like Simon's idea re: DCL. I only used VMS briefly in school and I > wasn't aware that DCL could be extended in that way. It's a nice way > to regularize at least the argument input. I'm looking into the implementation to see which ideas I can borrow. I think I have a "prettier" way of creating the syntax. > If all you want is to regularize input, another way might be to borrow > from the HTML fast-cgi interface. It doesn't guarantee anything about > interoperability per se, but it does arrange that programs get their > arguments in recognizable key:value pairs. > >> The (forced) "computer upgrade" cost me my mail archive >> (I don't leave mail stored on server :< ) > > Ouch. I don't leave anything on provider servers either, but my own > IMAP server is backed up regularly. I move my mail archive to a little server that does my DNS, TFTP, font, DHCP, etc. services periodically. Lets me view it as mail (instead of as a raw "mailbox"). That box is the only thing that runs 24/7/365, here so it's the destination for just about everything! [It's more of an appliance than a server] In my eagerness to get rid of kit before the annual equipment upgrade cycle, I opted to replace that box -- it had been running for several years (uptime was over 1000 days) so I felt it "deserved" to be replaced. I moved everything onto a *smaller*, faster, less power-hungry box. Life was good. Another bit of kit into the bin! :> Unfortunately, the box only lasted a few weeks before the disk (apparently) spun a bearing. Current thinking is it wasn't a suitable orientation to *mount* the disk and/or too close to the main heatsink (the box is REALLY small! had to shoehorn the 2.5" disk in there just to get it to fit!). Anyway, easy to recreate everything for which I had sources -- even my databases! Mail archive has never been something I considered "precious" so that was *the* backup (aside from what was on my MUA at the time). Rather than risk another disk in the "new" appliance (which was never intended to have a physical disk drive within), I replaced *that* with another appliance that *does* accommodate a disk drive (even having a fan just for the drive). <shrug> Moral: "If it ain't broke, don't fix it!" When the box that hosts the MUA went down, I took the opportunity to replace it (preserving the mail that *was* on it at the time). So, I managed to get rid of some kit -- and the most recent chunk of my mail archive in the process. <frown> > What I was thinking about is less important given compile time parser > generation ... we were talking about providing API object and entry > point addresses to runtime generated code. > > The relevance (if any) depends on whether you want to allow grammar > extensions direct access to your device API: i.e. whether the > extensions should be allowed to manipulate your (part of the) device > or whether they have to go through your provided language to do it. The goal is for people to be able to extend the "system" -- in whichever directions THEY choose -- and provide a simple way of configuring those enhancements (software/hardware/systems). It's a "low value" operation and, as such, doesn't merit lots of resources. OTOH, it shouldn't require "surgery" to tweek variables deep in the sources (these sorts of "selections" should be very visible without detailed inspection). I've considered it in the context of "settings" -- almost like twiddling envars -- except it need not be. I.e., the "commands" could initiate *actions* if so desired. I *hadn't* considered it as a "programming/scripting language" (which is why I called it a "command parser" and presented command line argument parsing and configuration file parsing as the examples to illustrate its intent. There *could* be some value to a real procedural language, there. But, when I conveyed the "Forth" suggestion to colleagues, it didn't fare well (I suspect that had more to do with "Forth" than the "programming language aspect" of the idea -- almost provincial! [No desire to take on THAT fight, thankyouverymuch!] >>>>> In either case, the additional parser should get the first crack at >>>>> input with Don's own parser as a fallback. >>>> >>>> Hmmm... I had considered the opposite approach: let me verify the >>>> input is/isn't a "common command" before exposing the input to the >>>> "other" parser. The thought being: common commands are then >>>> implicitly invariant (you can't change the syntax of them) AND >>>> they "always work" (even if the additional parser has bugs in its >>>> implementation). >>> >>> You don't want to "front end" the extensions ... if one of your >>> commands is redefined, it won't work if you grab it first. >> >> That was exactly the point: that the common commands are *common* >> and always behave exactly the same. (as well as "always working" >> regardless of how much the other guy mucks with the interface). > > That's the safe approach, but it's not terribly friendly ... That's why they were called "common commands" -- things that you can *rely* upon regardless of implementation. > particularly in the case of a reusable component where you don't have > any say in the use. A new developer may want to completely change the > approach to the command set. Well, he can always rewrite the subsystem! :> I doubt it will take me more than a week or two to put it in place (though in this first instance, there are two other subsystems that I want to add/modify in the process for a more integrated experience) >> It's a tough call -- assume competence in EVERYTHING? Or, just >> assume competence in their knowledge of their "extensions"?? > > It's reasonable to expect that many developers will have little > experience with _formal_ parsing methods and tools ... quite a lot of > applications can get by with RegEx or even just separator tokenization > and have no need of any formal grammar. Exactly. That was my (upthread) observation of what I've encountered in config file parsers, command line option parsing, etc. When you consider how "rich" some of those environments are (options, etc.), it's a wonder that so much ad hoc parsing is done! I can see "evolution"/feeping creaturism explaining some of it (i.e., "it wasn't this complex when we started") but I doubt that's the real cause. I suspect it's more one of familiarity: you write "generic code" everyday. So, writing something to extract a numeric value from the "second whitespace-delimited field" in a statement is trivial. OTOH, writing a formal grammar so that a *tool* can do this for you AUTOMATICALLY probably means you spend more time relearning the tool than you would have spent writing the code! <shrug>
[toc] | [prev] | [next] | [standalone]
| From | George Neuner <gneuner2@comcast.net> |
|---|---|
| Date | 2014-10-26 14:36 -0400 |
| Message-ID | <1a9q4al0oqqlvtrh8bi85nmi8oh3rc8bs2@4ax.com> |
| In reply to | #18962 |
Hi Don, On Sun, 26 Oct 2014 08:41:42 -0700, Don Y <this@is.not.me.com> wrote: >On 10/26/2014 12:47 AM, George Neuner wrote: > >> What I was thinking about is less important given compile time parser >> generation ... we were talking about providing API object and entry >> point addresses to runtime generated code. >> >> The relevance (if any) depends on whether you want to allow grammar >> extensions direct access to your device API: i.e. whether the >> extensions should be allowed to manipulate your (part of the) device >> or whether they have to go through your provided language to do it. > >The goal is for people to be able to extend the "system" -- in whichever >directions THEY choose -- and provide a simple way of configuring those >enhancements (software/hardware/systems). It's a "low value" operation >and, as such, doesn't merit lots of resources. OTOH, it shouldn't >require "surgery" to tweek variables deep in the sources (these sorts >of "selections" should be very visible without detailed inspection). I guess the real question is why *you* should be providing that? You've already given them a way to control your gizmo and they have the gizmo's API with which to construct a different command set if they want. >I've considered it in the context of "settings" -- almost like twiddling >envars -- except it need not be. I.e., the "commands" could initiate >*actions* if so desired. > >I *hadn't* considered it as a "programming/scripting language" (which >is why I called it a "command parser" and presented command line >argument parsing and configuration file parsing as the examples to >illustrate its intent. > >There *could* be some value to a real procedural language, there. >But, when I conveyed the "Forth" suggestion to colleagues, it didn't >fare well (I suspect that had more to do with "Forth" than the >"programming language aspect" of the idea -- almost provincial! Forth - and Lisp, too - has a bad rep in many circles ... which is unfortunate because sometimes it may be the simplest answer to the problem. From what I've read I don't think you're really needing a programming language. But then I'm still trying to figure out how sophisticated the commands are likely to be ... they don't look like much from your examples, but the discussion hints at more complexity. >>> It's a tough call -- assume competence in EVERYTHING? Or, just >>> assume competence in their knowledge of their "extensions"?? >> >> It's reasonable to expect that many developers will have little >> experience with _formal_ parsing methods and tools ... quite a lot of >> applications can get by with RegEx or even just separator tokenization >> and have no need of any formal grammar. > >Exactly. That was my (upthread) observation of what I've encountered >in config file parsers, command line option parsing, etc. When you >consider how "rich" some of those environments are (options, etc.), >it's a wonder that so much ad hoc parsing is done! I can see >"evolution"/feeping creaturism explaining some of it (i.e., "it wasn't >this complex when we started") but I doubt that's the real cause. > >I suspect it's more one of familiarity: you write "generic code" >everyday. So, writing something to extract a numeric value from >the "second whitespace-delimited field" in a statement is trivial. >OTOH, writing a formal grammar so that a *tool* can do this for >you AUTOMATICALLY probably means you spend more time relearning the >tool than you would have spent writing the code! I think it's more panic upon seeing the manual's introduction to the method theory. The vast majority of programmers today have little or no formal schooling, and language theory waters (doesn't matter syntactic or semantic) get deep very fast. As with most things, deep understanding isn't necessary to use the tools, but a programmer does need at least a passing familiarity with the tool's method to understand what it is trying to do and why it is failing. In this regard parser generators are less forgiving than the average compiler and it doesn't much matter which method(s) the tool uses - you can make as big a mess with LL(n) as with (LA|S)?LR(1) and quite easily hang yourself using PEG or GLR. Learning to use a parser generator isn't really any harder than learning any other programming language, but the documentation tends to be scarier. This isn't helped by the tendency of tool developers to minimally document and to relate their wares to existing tools that the user is presumed already to be familiar with. ><shrug> Nothing to be done about it except try to convince people that it really isn't that hard and that, for most purposes, they really should be using a generator tool rather than rolling their own. The only really valid exceptions are very simple interface "languages" and very tiny systems 8-) that can't afford the overhead of a generated parser. The constant overhead of a generated parser is fairly large: with care using Bison you can shoehorn a fairly complex language into ~10KB ... but even the simplest VERB NOUN command parser is difficult to bring in under ~3KB. And Bison actually is pretty good at making small parsers - there are a few tools that are better, but many more are worse. However, I think even the parser size argument is losing weight as the average "small" system keeps getting bigger (32-bit ARM running Linux toasting bread, etc.). Moreover, many small system developers are comfortable using (some form of) RegEx to handle interfaces and probably most have no clue about its intrinsic overhead. George
[toc] | [prev] | [next] | [standalone]
| From | Don Y <this@is.not.me.com> |
|---|---|
| Date | 2014-10-26 12:37 -0700 |
| Message-ID | <m2jih1$548$1@speranza.aioe.org> |
| In reply to | #18969 |
Hi George,
On 10/26/2014 11:36 AM, George Neuner wrote:
>>> The relevance (if any) depends on whether you want to allow grammar
>>> extensions direct access to your device API: i.e. whether the
>>> extensions should be allowed to manipulate your (part of the) device
>>> or whether they have to go through your provided language to do it.
>>
>> The goal is for people to be able to extend the "system" -- in whichever
>> directions THEY choose -- and provide a simple way of configuring those
>> enhancements (software/hardware/systems). It's a "low value" operation
>> and, as such, doesn't merit lots of resources. OTOH, it shouldn't
>> require "surgery" to tweek variables deep in the sources (these sorts
>> of "selections" should be very visible without detailed inspection).
>
> I guess the real question is why *you* should be providing that?
> You've already given them a way to control your gizmo and they have
> the gizmo's API with which to construct a different command set if
> they want.
I have to provide some of these features to get ANY system configured, etc.
I can do this as a completely independant "service" and require others
to invent their own solution to THEIR problems (the customizations that
they may implement).
*Or*, I can put facilities in place that encourage them to "do as I have
done" in the hopes of a tighter, more consistent implementation. I
expect people to be inherently lazy and opt to *modify* something
that is proven as "working" rather than trying to create something
new, from scratch.
But, in doing so, I have to make a decent attempt at anticipating the sorts
of things they *may* want/need to do.
(e.g., expecting everything to be VERB NOUN pairs might rub some folks
the wrong way)
>> I've considered it in the context of "settings" -- almost like twiddling
>> envars -- except it need not be. I.e., the "commands" could initiate
>> *actions* if so desired.
>>
>> I *hadn't* considered it as a "programming/scripting language" (which
>> is why I called it a "command parser" and presented command line
>> argument parsing and configuration file parsing as the examples to
>> illustrate its intent.
>>
>> There *could* be some value to a real procedural language, there.
>> But, when I conveyed the "Forth" suggestion to colleagues, it didn't
>> fare well (I suspect that had more to do with "Forth" than the
>> "programming language aspect" of the idea -- almost provincial!
>
> Forth - and Lisp, too - has a bad rep in many circles ... which is
> unfortunate because sometimes it may be the simplest answer to the
> problem.
That's true of all tools. How many folks avoid dynamic memory allocation
in the belief that it is (inherently!) unsafe? Or, recursive implementations
("what happens if the recursion never stops?" "Well, same thing if your
iteration never stops!")
> From what I've read I don't think you're really needing a programming
> language. But then I'm still trying to figure out how sophisticated
> the commands are likely to be ... they don't look like much from your
> examples, but the discussion hints at more complexity.
I don't know as I can't envision the varieties of hardware (and software)
that will be globbed on. E.g., I had not envisioned the need for a
conditional operation -- yet, in hindsight, it seems like it could be
extremely useful! ("Do this -- unless you CAN'T! In which case, do this
OTHER thing!")
But, how far do you take this before you begin to delve into the realm
of "just add it to the executable directly"?
[When I offered the "C interpreter" as an alternative to Forth -- to see
if the resistance was due to the language or the mechanism -- this was
the reply! "If you're going to write code, then why create another
means of writing code OUTSIDE the system??"]
>>>> It's a tough call -- assume competence in EVERYTHING? Or, just
>>>> assume competence in their knowledge of their "extensions"??
>>>
>>> It's reasonable to expect that many developers will have little
>>> experience with _formal_ parsing methods and tools ... quite a lot of
>>> applications can get by with RegEx or even just separator tokenization
>>> and have no need of any formal grammar.
>>
>> Exactly. That was my (upthread) observation of what I've encountered
>> in config file parsers, command line option parsing, etc. When you
>> consider how "rich" some of those environments are (options, etc.),
>> it's a wonder that so much ad hoc parsing is done! I can see
>> "evolution"/feeping creaturism explaining some of it (i.e., "it wasn't
>> this complex when we started") but I doubt that's the real cause.
>>
>> I suspect it's more one of familiarity: you write "generic code"
>> everyday. So, writing something to extract a numeric value from
>> the "second whitespace-delimited field" in a statement is trivial.
>> OTOH, writing a formal grammar so that a *tool* can do this for
>> you AUTOMATICALLY probably means you spend more time relearning the
>> tool than you would have spent writing the code!
>
> I think it's more panic upon seeing the manual's introduction to the
> method theory. The vast majority of programmers today have little or
> no formal schooling, and language theory waters (doesn't matter
> syntactic or semantic) get deep very fast.
Or, a lack of patience -- as exemplified by wanting to write code
"on day one" (before they even know where that code is *headed*).
> As with most things, deep understanding isn't necessary to use the
> tools, but a programmer does need at least a passing familiarity with
> the tool's method to understand what it is trying to do and why it is
> failing. In this regard parser generators are less forgiving than the
> average compiler and it doesn't much matter which method(s) the tool
> uses - you can make as big a mess with LL(n) as with (LA|S)?LR(1) and
> quite easily hang yourself using PEG or GLR.
My experiences with lex/yacc were far less "pleasant" than writing
arbitrarily complex code in a procedural/object language! Too much
head scratching as there were interactions "across" the grammar
that were only apparent in hindsight. The way I thought of the various
constructs "as a human being" was very different from the way the tools
NEEDED me to think of them. This doesn't appear in *most* languages
(aside from unfortunate issues like "foo =- 2;")
> Learning to use a parser generator isn't really any harder than
> learning any other programming language, but the documentation tends
> to be scarier. This isn't helped by the tendency of tool developers
> to minimally document and to relate their wares to existing tools that
> the user is presumed already to be familiar with.
There tends to be far more abstraction involved. People seem to have
a problem with abstraction -- always wanting to know "why do you want
to do that" or "what are you trying to do".
"Timmy has three apples. Mary has one. How many apples would Timmy have
to give to Mary in order for them to each have the same number of apples?"
"Why should Timmy have to give her ANY? Why couldn't *Mary* bring the
right number of apples to school??"
[Of course, the correct answer is that Timmy should quickly EAT two of his
apples and the problem then disappears! :> ]
>> <shrug>
>
> Nothing to be done about it except try to convince people that it
> really isn't that hard and that, for most purposes, they really should
> be using a generator tool rather than rolling their own.
Check your mail. I think the solution I proposed will be *so* tempting
to others that they'll just "cut and paste; edit to taste". I figured
easier to take this offlist than deal with the inevitable complaints about
"lengthy posts"... :>
> The only really valid exceptions are very simple interface "languages"
> and very tiny systems 8-) that can't afford the overhead of a
> generated parser. The constant overhead of a generated parser is
> fairly large: with care using Bison you can shoehorn a fairly complex
> language into ~10KB ... but even the simplest VERB NOUN command parser
> is difficult to bring in under ~3KB. And Bison actually is pretty
> good at making small parsers - there are a few tools that are better,
> but many more are worse.
>
> However, I think even the parser size argument is losing weight as the
> average "small" system keeps getting bigger (32-bit ARM running Linux
> toasting bread, etc.). Moreover, many small system developers are
> comfortable using (some form of) RegEx to handle interfaces and
> probably most have no clue about its intrinsic overhead.
But even big systems often have "regions" in which severe constraints
are placed on the implementation. E.g., many of those "big Linux
implementation" compress the kernel to economize on FLASH/ROM -- this
suggests an unwillingness to add "unnecessary resources" for a one-time
event (decompressing the kernel/system on IPL). The same sorts of
arguments can apply to "setting configuration options" ("Can't we just
set some bitmaps in a hidden corner of FLASH?")
Or, things like delivering options in BOOTP packets, etc. Sometimes
you just can't "do what you want" (or what would be "ideal")
[toc] | [prev] | [next] | [standalone]
Page 1 of 3 [1] 2 3 Next page →
Back to top | Article view | comp.arch.embedded
csiph-web