Code Monkey home page Code Monkey logo

Comments (6)

quark17 avatar quark17 commented on September 23, 2024

In src/comp/Parser/BSV/CVParser.lhs, there are parsing functions pExpressionSimple and pExpression, where the only difference is that the first excludes the ternary conditional operator (? :). The first is only used in one place, in the definition of pCondExpression, which is the parsing of the boolean condition in conditional syntax -- presumably this is to avoid ambiguity of nested conditional operators, so you have to put parentheses around them.

The parsing of case-expressions is done by calling the parser for case-statements and just telling it to allow naked expressions (see pCasePrimary which sets allowNakedExpr and calls pImperativeCase). In the parsing of case-statements, the arm is parsed by pImperativeStmt. This calls pImperativeStmtWithAttrs which has a long list of parsers that it tries, and I believe it's the last one (pImperativeDeclOrAssignSemi that calls pImperativeDeclOrAssign) which handles naked expressions. Or it should. It could be something else earlier in the list is parsing the start of the expression but failing on the rest; it probably just needs try to be added to it, so that the failure doesn't cause the parsing to stop immediately.

I don't think the issue has anything to do with case-expressions or case-statements specifically, but with the fact that x == y doesn't parse as a statement (and thus doesn't parse as the arm of a case). That is, we get the same error if we try this:

module mkTest (Empty);
  int x = 1;
  int y = 2;
  x == y;
endmodule

but it parses if we add parentheses around the expression (and BSC fails in the later typecheck stage, after parsing has succeeded).

from bsc.

quark17 avatar quark17 commented on September 23, 2024

FYI, you don't need the keyword matches here, since you're not using any pattern matching. An ordrinary non-matching case would be fine. (You get the same error, either way.) I notice that the BSV Ref Guide doesn't document non-matching case, which should probably be fixed.

from bsc.

quark17 avatar quark17 commented on September 23, 2024

Ah, I think I've solved it.

In pImperativeDeclOrAssign, the last two things that it tries are pVarTypeCases and naked expressions. As the comment explains, it calls pVarTypeCases twice: the first time, if it fails, it goes on to try a naked expression; then, if parsing a naked expression fails, it calls pVarTypeCases again, this time for its error message. The result is that both are tried, but the error message is for the more common case.

The code for trying a naked expressions looks for a semicolon after what it has parsed, to guarantee that it has consumed the entire statement. But the code for trying pVarTypeCases doesn't do this. When the expression x==y is encountered, the parsing of pVarTypeCases can match the first part of it (though I'm not entirely sure how, maybe the bare variable?) and so we never get to trying for a naked expression: the statement parses, but then we get an error that the next part isn't expected after a statement. If I change the try of pVarTypeCases to only match if it consumes up to a semicolon, then the above examples parse. That is:

<|> try (do
           s <- pVarTypeCases2
           lookAhead pSemi
           return s)

However, I don't know if this is OK to do, so I will have to test it. I also don't know if it's safe to assume that there will always be a semicolon -- it's what the try for the naked expression does, so that would also be broken, if not -- but I would guess so?

Looking close at why pVarTypeCases matches on x==y. It's the first option that is matching, where it calls pQualIdOrTuple (which matches an identifier like x) and then it calls pImperativeWithVar, which looks for any "suffix" on the identifier (with pPrimaryWithSuffix) but is OK with not finding any (the return e branch of pPrimaryWithSuffix), and then it attempts to parse what comes after the variable, which can be <= or <- or =, but it can apparently also be nothing (pImperativeWithExprNakedExpr). I'm not sure why that is there -- maybe a better fix (than looking for a semicolon) is to just remove pImperativeWithExprNakedExpr as an option within pImperativeWithVarCall, since that case is covered by the later trying of a naked expression. Yeah, I'm tempted by that approach, and will try testing it.

from bsc.

yannickl96 avatar yannickl96 commented on September 23, 2024

Thank you very much for the elaborate reply! For now I will work around this behavior by just wrapping the expression in parentheses. On a different note, is there documentation available on the internal architecture of the compiler?

from bsc.

quark17 avatar quark17 commented on September 23, 2024

is there documentation available on the internal architecture of the compiler?

I don't believe there is anything compiled in one place, yet. Feel free to ask questions here on GitHub (in an Issue or a Discussion) or in the mailing lists (bsc-dev or b-lang-discuss -- I would recommend using bsc-dev for questions that are only relevant to developers, to keep traffic light for people who are just users and might not be interested). In those four places, I have written up long responses on a number of topics, and it's my intention to collect them up and put them in a single place, but I haven't decided what that is yet. GitHub provides a wiki feature, that we could use; but maybe a document (in bsc/doc/) would be better.

For example, some writeups are:

from bsc.

quark17 avatar quark17 commented on September 23, 2024

maybe a better fix (than looking for a semicolon) is to just remove pImperativeWithExprNakedExpr as an option within pImperativeWithVarCall

When I do this, there is a testcase (ImperativeFunctionBeginEndMissingReturn.bsv in bsc.syntax/bsv05/) that fails with a different error. That test has a function body like this:

function int f();
  ...
  y;
endfunction

Currently, BSC gives this error:

Error: "ImperativeFunctionBeginEndMissingReturn.bsv", line 7, column 4: (P0106)
  Unassigned expressions forbidden in expression block; perhaps `return' is
  missing before the expression?

That's because pImperativeWithExprNakedExpr accepts y to be parsed but then reports it with this special error. If I remove that, then the parser just rejects the code with the typical "unexpected tokens" error:

Error: "ImperativeFunctionBeginEndMissingReturn.bsv", line 7, column 4: (P0005)
  Unexpected `;'; expected `=', `<-', `<=', type parameters, `{', identifier
  starting with lowercase, `.', `(', or `['

I'm not convinced that the existing message is the best. But I don't feel strongly enough to change things. So, instead of removing pImperativeWithExprNakedExpr, I think I'll leave it in, but make it only parse if it consumes all the way to the semicolon.

from bsc.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.