Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
    Corneliu
    @corneliutusnea
    Guys, do you know if there is a similar(-ish) library like Sprache for JavaScript ? I'm trying to build a text editor for my language in JS as an extension to Monaco and I think I'll have to process all the text in JS so I avoid roundtrips to the server for the compilation
    Nicholas Blumhardt
    @nblumhardt
    @corneliutusnea none, but looks like there are some interesting options - http://bennu-js.com/ looks pretty complete
    depending on what you want to do (e.g. just a highlighter) you might get away with just writing a tokenizer instead - worth looking into if it's just a quick project
    Corneliu
    @corneliutusnea
    thanks, I was looking at chevrotain atm
    I might just try to write my own using the VS Code Monaco Text Editor as I need it as a language extension for the editor
    Frederik Madsen
    @Zarickan
    Is there any documentation somewhere?
    Perhaps an example on how to parse a basic mathematical equation like "5 + 10 * 2"?
    Michal Pawluk
    @nekomatic
    @corneliutusnea , you may try my parser (inspired also by Sprache) https://github.com/nekomatic/ironik, it is written in Kotlin but it should be compilable to JavaScript - I naven't tried this myself yet... Note it does not yet suppot operator precedence but this may be tricked by using complex rules
    Michal Pawluk
    @nekomatic
    If you are fine with a Lexer based parser you shoudl try ANTLR4, it does generate Javascript code.
    Nicholas Blumhardt
    @nblumhardt
    @Zarickan the second example linked from the README seems close to what you're looking for: https://github.com/sprache/sprache#examples-and-tutorials
    Josh Williams
    @jjwilliams42
    Hellooo, I had some questions regarding Sprache usage. I emailed @nblumhardt awhile back and he gave me some general direction, but I'm having a hard time getting going with Sprache. Would anyone be able to help me?
    Michal Pawluk
    @nekomatic
    @jackjwilliams have a look at https://github.com/IanWold/SpracheJSON. It's an easy to follow sample of Sprache usage.
    Darren R. Starr
    @darrenstarr
        public static class SyslogMessageParser
        {
            public class SyslogHeader
            {
                public int Pri { get; set; }
                public int Version { get; set; }
            }
    
            //    HEADER          = PRI VERSION 
            public static readonly Parser<SyslogHeader> Header =
                from pri in Pri
                from version in Version
                select new SyslogHeader
                {
                    Pri = pri,
                    Version = version
                };
    
            //    PRI = "<" PRIVAL ">"
            public static readonly Parser<int> Pri =
                from leading in Parse.WhiteSpace.Many().Optional()
                from lt in Parse.Char('<')
                from priVal in PriVal
                from gt in Parse.Char('>')
                select priVal;
    
            //    PRIVAL          = 1*3DIGIT ; range 0 .. 191
            public static readonly Parser<int> PriVal =
                Parse.Number
                .Select(x => int.Parse(x));
    
            //    VERSION         = NONZERO-DIGIT 0*2DIGIT
            public static readonly Parser<int> Version =
                from ws in Parse.WhiteSpace.Many().Optional()
                from value in Parse.Number
                select int.Parse(value);
        }
    Can anyone tell me why the above code generates
    Message: System.TypeInitializationException : The type initializer for 'libsyslog.SyslogMessageParser' threw an exception.
    ---- System.ArgumentNullException : Value cannot be null.
    Parameter name: parser
    Nicholas Blumhardt
    @nblumhardt
    @darrenstarr static members are initialized top-to-bottom, so when the Header parser is initialized, the Pri parser will still be null. You can reverse the order of the declarations to fix this, or use Parse.Ref(() => Pri) to lazily reference it.
    Darren R. Starr
    @darrenstarr
    @nblumhardt thanks... that worked... of course... the scary thing is that PriVal and Pri work in the order they are in.... Gotta love it. I'm back to programming C++ where order counts it seems
    Matthew McConnell
    @maca134
    having a little trouble parsing recursive structures. Im 90% there but im missing something, its only parsing a limited number of items
    no errors so kinda dont know were to go lol :(
    Matthew McConnell
    @maca134
    sp is anyone alive in here?
    Martijn Hoekstra
    @martijnhoekstra
    it's a pretty low-traffic room
    Nicholas Blumhardt
    @nblumhardt
    @maca134 try adding a .End() to the very end of your outermost rule; this will cause an error to be returned if the whole input can't be parsed, rather than the default behaivour of just parsing as much as can be matched
    Andrew Shaw Care
    @andrewshawcare
    Is there a way to have a parser error thrown if there is a maximum length constraint?
    It looks like Repeat will throw if there is a minimum length violation, but will just consume up to the maximum length.
    I know this might not make sense for parsing the stream of characters, but wondering if there's any way to address maximum length constraints (in this case, the language puts a maximum length constraint on a variable name)
    I have the following:
    public static readonly Parser<string> VariableName =
          from firstCharacter in Parse.Letter.Or(Parse.Char('_')).Once().Text()
          from remainingCharacters in Parse.LetterOrDigit.Or(Parse.Char('_')).Repeat(minimumCount: 0, maximumCount: 255).Text()
          select $"{firstCharacter}{remainingCharacters}";
    Andrew Shaw Care
    @andrewshawcare
    That "works", but if provided a string that exceeds the length requirements will just chop the stream (which makes sense), but wondering if there's a way to look ahead, realize there are "extra" candidate characters that would have been matched (i.e. the stream has remaining characters that would have been consumed by the current parsing pattern) and to throw if that's the case.
    Andrew Shaw Care
    @andrewshawcare
    Actually, maybe I can get by without throwing. Wanted to fail fast, but will try just truncating as it is for now.
    Chris
    @furesoft
    why is nobody managing the repo right now? no acceptance of pull requests
    Nicholas Blumhardt
    @nblumhardt
    @furesoft the usual reasons :-)
    I can only see one mergeable PR waiting, though, for an unsolicited change with no corresponding issue and no +1 upvotes... Not ideal, it'd be great to get that person a response, but doesn't seem too critical?
    If you have some time to help dig through the issue list and sort out what's what, any and all help would be welcome :+1:
    Chris
    @furesoft
    how can i give a upvote?
    Nicholas Blumhardt
    @nblumhardt
    @furesoft it's the "+ 🙂" icon in the top right of an issue/PR description
    Martijn Hoekstra
    @martijnhoekstra
    When working with IInput, should I advance then get current, or get current then advance?
    Martijn Hoekstra
    @martijnhoekstra
    Also, are there direct ways to construct an IOption value?
    Martijn Hoekstra
    @martijnhoekstra

    I'm now using

    public static IOption<T> Some<T>(T t) => Parse.Return(t).Optional()(new Input("")).Value;
    public static IOption<T> None<T>()  {
      Parser<T> p = ((IInput i) => Result.Failure<T>(i, "failue", Enumerable.Empty<String>()));
      return p.Optional()(new Input("")).Value;
    }

    but that honestly feels a bit silly

    John Zabroski
    @jzabroski
    @nblumhardt How many open source projects have you started? AutoFac, SeriLog, Sprache? I didn't know about Sprache until today. Similarly, I didn't know Jonathan Magnan was behind HtmlAgilityPack and EFPlus. It's pretty amazing how most of the libraries I use come from a very small group of individuals. (Well, we use NLog at work, but I would probably use SeriLog or Its.Log if given a choice...)
    Nicholas Blumhardt
    @nblumhardt
    @jzabroski :-)
    John Zabroski
    @jzabroski

    I actually just found SuperPower, too, after my comment. I kind of wonder if the SuperPower API could be simplified a bit further to make working with tokens nicer.

    However, it's not immediately clear to me why Sprache can't do Tokenization and why SuperPower is needed at all.

    I read through the original motivation of SuperPower - to do tokenization to get better error messages and reduce backtracking due to single-character-at-a-time context.

    Years ago, I also read through Terrance Parr's ANTLR book and tried to grasp a lot of the little computer science concepts like when you can convert a LL(*) grammar to discrete finite automata (I hope I'm remembering this right), so I believe what you were describing in your SuperPower intro blog post is the fundamental limitaitons of LL(1) parsers. It's not the tokenization that kills you, or even the LL(1) model. It's :
    a) Lack of search for ambiguities / aliasing
    b) Need to "thread" through the parser combinators a memo table to reduce to polynomial time the handling of left-recursive production rules

    One thing I believe I recall learning from Parr was the ability to "infer" when a rule could be "rephrased" in such a way to improve performance. For example, if the left recursive production rule is deep in the grammar and not at the top-level, you can greedily consume the entire "forest" from the point at which the rule starts until it certainly ends. Then you can pare the forest down. And this paring probably doesn't need to have the same semantics as the rest of the program, since all you're doing is returning a Context back to the parent Grammar about where you finished reading.
    Alistair Curtis
    @roncitrus
    OK, I've been trying to get my head around this for a while now, excuse my noobyness. I want to be able to parse a string of integers (e.g. "14 23 1 5") and have them put into a List<int>. Sounds so simple, and I could easily do it with the normal .Split method, but I'm trying to solve the 'Forth' Exercism challenge, and I'm falling at this first hurdle. I can parse the first number, and have it populate the list, but I can't seem to get any further. Once the first number is parsed, it just stops. Can anyone give a beginner a clue?
    Nicholas Blumhardt
    @nblumhardt
    Hi @roncitrus - do you have .Token() applied to your int parser, so that whitespace is eaten?
    Alistair Curtis
    @roncitrus

    Hi - I've tried this :
    input = "14 23 1 5"; Parser<string> Numbers = Parse.Number.Token(); var parsed = Numbers.Parse(input);

    if I add 'AtLeastOnce()', I can see that the Parser should now be for <IEnumerable<string>>, but parsed still comes back with "14".

    Stephen Grattan
    @keyedit
    I have a small language I'm trying to parse. The basics are really straight forward using Sprache but I can't seem to get past that. I'm wondering if it's my lack of knowledge or a restriction in the tool. The basic construct is an if statement: if <X> is 'Yes' and of course we could have conjunctions if <X> is 'Yes' AND <Y> is 'No'. I have written the parsers using Sprache to handle those and even a triple conditional if <X> is 'Yes' AND <Y> is 'No' AND <Z> is 'Maybe'. However I can't seem to get to the next level where I want to define multiple conjuctions: if <X> is 'Yes' AND <Y> is 'No' AND <Z> is 'Maybe' AND <W> is 'Po'.... I'd really appreciate some help as I can't seem to find any examples where conjuctions are parsed. Thanks in advance.
    Stephen Grattan
    @keyedit
    Here's the grammar. Note the last parser (AndConditionParser ) doesn't handle any more than three conditions (two ANDs).
        public static class IfGrammar
        {
            public static readonly Parser<Field> FieldParser =
                from open in Parse.Char('<')
                from value in Parse.Regex("[^<>]+")
                from close in Parse.Char('>')
                select new Field { Name = value };
    
            public static readonly Parser<QuotedString> QuotedStringParser =
                from open in Parse.Char('\'')
                from value in Parse.Regex("[^'']+")
                from close in Parse.Char('\'')
                select new QuotedString { Value = value };
    
            public static readonly Parser<UnaryCondition> UnaryConditionParser =
                from lhs in Parse.Token(FieldParser)
                from op in Parse.Regex("is not|is")
                from rhs in Parse.Token(QuotedStringParser)
                select new UnaryCondition { Lhs = lhs.Name, Operator = op, Rhs = rhs.Value };
    
            public static readonly Parser<AndCondition> AndConditionParser1 =
                from lhs in Parse.Token(UnaryConditionParser)
                from and in Parse.Regex("AND")
                from rhs in Parse.Token(UnaryConditionParser)
                select new AndCondition { Conditions = new List<Condition> { lhs, rhs } };
    
            public static readonly Parser<AndCondition> AndConditionParser2 =
                from lhs in Parse.Token(AndConditionParser1)
                from and in Parse.Regex("AND")
                from rhs in Parse.Token(UnaryConditionParser)
                select new AndCondition { Conditions = new List<Condition>(lhs.Conditions) { rhs } };
    
            public static readonly Parser<AndCondition> AndConditionParser =
                AndConditionParser2.Or(AndConditionParser1);
        }
    Nicholas Blumhardt
    @nblumhardt
    @keyedit you'll need to make the rules of the parser recurse; there's a sample that does this for typical arithmetic operators at https://github.com/sprache/Sprache/blob/develop/samples/LinqyCalculator/ExpressionParser.cs, which should be a good starting point; HTH!
    Tomas Jansson
    @mastoj

    I writing a parser for a template format that we are using here internally, but struggle with nested if statements. An example template could look like this:

    this is some text <<cs_{token='a string'}>>more text<<cs_{another_token='some string'}>>hello<<es_>><<else_{token3='abc'}>>wat<<else_{token4='wat'}>><<else_>>last text<<es_>>

    I manage to parse it if I drop the second nested <<cs_{another_token='some string}>> part, but I should be able to keep that as I see it. Any pointers on how I can solve the nested if, or conditional statements as they are called in the template?

    Tomas Jansson
    @mastoj
    Solved my issues. I must say it is a pretty nice lib to work with. Great job there!
    Tomas Jansson
    @mastoj
    Have anyone here created a parser for a template language where the document used is word/openxml. The structure of openxml sort of breaks keywords and special characters, so expressions might be spread over multiple xml elements. My first go is to sort of normalize/flatten the xml so all the relevant text is within the same xml tag, after that I should be able to treat the xml as text and parse it. I have found it working for most of a lot of the document I have, but I’ve also found som adjacent xml elements that I want to join/flatten, but they differ slightly in the structure so it is hard to predict the outcome of that join.