Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
C
capnproto
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
capnproto
Commits
359ea45a
Commit
359ea45a
authored
Jul 13, 2013
by
Kenton Varda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Continuing work on capnp C++ parser.
parent
cc8d8fc7
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
358 additions
and
63 deletions
+358
-63
capnpc2.c++
c++/src/capnp/compiler/capnpc2.c++
+36
-15
error-reporter.c++
c++/src/capnp/compiler/error-reporter.c++
+33
-0
error-reporter.h
c++/src/capnp/compiler/error-reporter.h
+46
-0
grammar.capnp
c++/src/capnp/compiler/grammar.capnp
+4
-0
lexer-test.c++
c++/src/capnp/compiler/lexer-test.c++
+9
-1
lexer.c++
c++/src/capnp/compiler/lexer.c++
+20
-19
lexer.h
c++/src/capnp/compiler/lexer.h
+11
-4
parser.cpp
c++/src/capnp/compiler/parser.cpp
+0
-0
parser.h
c++/src/capnp/compiler/parser.h
+16
-9
orphan.h
c++/src/capnp/orphan.h
+4
-4
stringify-test.c++
c++/src/capnp/stringify-test.c++
+11
-0
stringify.c++
c++/src/capnp/stringify.c++
+5
-4
test.capnp
c++/src/capnp/test.capnp
+7
-0
common-test.c++
c++/src/kj/parse/common-test.c++
+71
-0
common.h
c++/src/kj/parse/common.h
+85
-7
No files found.
c++/src/capnp/compiler/capnpc2.c++
View file @
359ea45a
...
@@ -22,33 +22,54 @@
...
@@ -22,33 +22,54 @@
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "lexer.h"
#include "lexer.h"
#include "parser.h"
#include <kj/vector.h>
#include <kj/vector.h>
#include <kj/io.h>
#include <kj/io.h>
#include <unistd.h>
#include <unistd.h>
#include <kj/debug.h>
#include <kj/debug.h>
#include "../message.h"
#include "../message.h"
#include <iostream>
class
CoutErrorReporter
:
public
capnp
::
compiler
::
ErrorReporter
{
public
:
void
addError
(
uint32_t
startByte
,
uint32_t
endByte
,
kj
::
String
message
)
override
{
std
::
cout
<<
"input:"
<<
startByte
<<
"-"
<<
endByte
<<
": "
<<
message
.
cStr
()
<<
std
::
endl
;
}
};
int
main
(
int
argc
,
char
*
argv
[])
{
int
main
(
int
argc
,
char
*
argv
[])
{
// Eventually this will be capnpc. For now it's just a dummy program that tests parsing.
// Eventually this will be capnpc. For now it's just a dummy program that tests parsing.
kj
::
Vector
<
char
>
input
;
// kj::Vector<char> input;
char
buffer
[
4096
];
// char buffer[4096];
for
(;;)
{
// for (;;) {
ssize_t
n
;
// ssize_t n;
KJ_SYSCALL
(
n
=
read
(
STDIN_FILENO
,
buffer
,
sizeof
(
buffer
)));
// KJ_SYSCALL(n = read(STDIN_FILENO, buffer, sizeof(buffer)));
if
(
n
==
0
)
{
// if (n == 0) {
break
;
// break;
}
// }
input
.
addAll
(
buffer
,
buffer
+
n
);
// input.addAll(buffer, buffer + n);
}
// }
//
// KJ_DBG(input);
// This input triggers a data corruption bug. Fix it before doing anything else!
kj
::
StringPtr
input
=
"@0xfa974d18d718428e; const x :Int32 = 1;"
;
CoutErrorReporter
errorReporter
;
KJ_DBG
(
input
);
capnp
::
MallocMessageBuilder
lexerArena
;
auto
lexedFile
=
lexerArena
.
initRoot
<
capnp
::
compiler
::
LexedStatements
>
();
capnp
::
compiler
::
lex
(
input
,
lexedFile
,
errorReporter
);
KJ_DBG
(
lexedFile
);
capnp
::
MallocMessageBuilder
message
;
capnp
::
MallocMessageBuilder
parserArena
;
auto
file
=
message
.
initRoot
<
capnp
::
compiler
::
LexedStatements
>
();
auto
parsedFile
=
parserArena
.
initRoot
<
capnp
::
compiler
::
ParsedFile
>
();
capnp
::
compiler
::
lex
(
input
,
file
);
capnp
::
compiler
::
parseFile
(
lexedFile
.
getStatements
(),
parsedFile
,
errorReporter
);
KJ_DBG
(
file
);
capnp
::
MallocMessageBuilder
parserArena2
;
parserArena2
.
setRoot
(
parsedFile
.
asReader
());
//KJ_DBG(parsedFile);
return
0
;
return
0
;
}
}
c++/src/capnp/compiler/error-reporter.c++
0 → 100644
View file @
359ea45a
// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "error-reporter.h"
#include <unistd.h>
namespace
capnp
{
namespace
compiler
{
ErrorReporter
::~
ErrorReporter
()
noexcept
(
false
)
{}
}
// namespace compiler
}
// namespace capnp
c++/src/capnp/compiler/error-reporter.h
0 → 100644
View file @
359ea45a
// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ERROR_REPORTER_H_
#define ERROR_REPORTER_H_
#include "../common.h"
#include <kj/string.h>
namespace
capnp
{
namespace
compiler
{
class
ErrorReporter
{
public
:
virtual
~
ErrorReporter
()
noexcept
(
false
);
virtual
void
addError
(
uint32_t
startByte
,
uint32_t
endByte
,
kj
::
String
message
)
=
0
;
// Report an error at the given location in the input text. `startByte` and `endByte` indicate
// the span of text that is erroneous. They may be equal, in which case the parser was only
// able to identify where the error begins, not where it ends.
};
}
// namespace compiler
}
// namespace capnp
#endif // ERROR_REPORTER_H_
c++/src/capnp/compiler/grammar.capnp
View file @
359ea45a
...
@@ -27,6 +27,8 @@ using Cxx = import "/capnp/c++.capnp";
...
@@ -27,6 +27,8 @@ using Cxx = import "/capnp/c++.capnp";
$Cxx.namespace("capnp::compiler");
$Cxx.namespace("capnp::compiler");
# TODO(someday): Here's a case where parameterized types might be nice, but note that it would
# need to support primitive parameters...
struct LocatedText {
struct LocatedText {
value @0 :Text;
value @0 :Text;
startByte @1 :UInt32;
startByte @1 :UInt32;
...
@@ -169,6 +171,8 @@ struct Declaration {
...
@@ -169,6 +171,8 @@ struct Declaration {
struct Union {}
struct Union {}
struct Group {}
struct Interface {}
struct Interface {}
struct Method {
struct Method {
...
...
c++/src/capnp/compiler/lexer-test.c++
View file @
359ea45a
...
@@ -29,6 +29,13 @@ namespace capnp {
...
@@ -29,6 +29,13 @@ namespace capnp {
namespace
compiler
{
namespace
compiler
{
namespace
{
namespace
{
class
TestFailingErrorReporter
:
public
ErrorReporter
{
public
:
void
addError
(
uint32_t
startByte
,
uint32_t
endByte
,
kj
::
String
message
)
override
{
ADD_FAILURE
()
<<
"Parse failed: ("
<<
startByte
<<
"-"
<<
endByte
<<
") "
<<
message
.
cStr
();
}
};
template
<
typename
LexResult
>
template
<
typename
LexResult
>
kj
::
String
doLex
(
kj
::
StringPtr
constText
)
{
kj
::
String
doLex
(
kj
::
StringPtr
constText
)
{
// Parse the given string into the given Cap'n Proto struct type using lex(), then stringify the
// Parse the given string into the given Cap'n Proto struct type using lex(), then stringify the
...
@@ -47,7 +54,8 @@ kj::String doLex(kj::StringPtr constText) {
...
@@ -47,7 +54,8 @@ kj::String doLex(kj::StringPtr constText) {
}
}
MallocMessageBuilder
message
;
MallocMessageBuilder
message
;
auto
file
=
message
.
initRoot
<
LexResult
>
();
auto
file
=
message
.
initRoot
<
LexResult
>
();
EXPECT_TRUE
(
lex
(
text
,
file
));
TestFailingErrorReporter
errorReporter
;
EXPECT_TRUE
(
lex
(
text
,
file
,
errorReporter
));
kj
::
String
result
=
kj
::
str
(
file
);
kj
::
String
result
=
kj
::
str
(
file
);
for
(
char
&
c
:
result
)
{
for
(
char
&
c
:
result
)
{
// Make it easier to write golden strings below.
// Make it easier to write golden strings below.
...
...
c++/src/capnp/compiler/lexer.c++
View file @
359ea45a
...
@@ -28,16 +28,16 @@
...
@@ -28,16 +28,16 @@
namespace
capnp
{
namespace
capnp
{
namespace
compiler
{
namespace
compiler
{
bool
lex
(
kj
::
ArrayPtr
<
const
char
>
input
,
LexedStatements
::
Builder
result
)
{
namespace
p
=
kj
::
parse
;
Lexer
lexer
(
Orphanage
::
getForMessageContaining
(
result
));
Lexer
::
ParserInput
parserInput
(
input
.
begin
(),
input
.
end
());
bool
lex
(
kj
::
ArrayPtr
<
const
char
>
input
,
LexedStatements
::
Builder
result
,
kj
::
Maybe
<
kj
::
Array
<
Orphan
<
Statement
>>>
parseOutput
=
ErrorReporter
&
errorReporter
)
{
lexer
.
getParsers
().
statementSequence
(
parserInput
);
Lexer
lexer
(
Orphanage
::
getForMessageContaining
(
result
),
errorReporter
);
if
(
!
parserInput
.
atEnd
())
{
auto
parser
=
p
::
sequence
(
lexer
.
getParsers
().
statementSequence
,
p
::
endOfInput
);
return
false
;
}
Lexer
::
ParserInput
parserInput
(
input
.
begin
(),
input
.
end
());
kj
::
Maybe
<
kj
::
Array
<
Orphan
<
Statement
>>>
parseOutput
=
parser
(
parserInput
);
KJ_IF_MAYBE
(
output
,
parseOutput
)
{
KJ_IF_MAYBE
(
output
,
parseOutput
)
{
auto
l
=
result
.
initStatements
(
output
->
size
());
auto
l
=
result
.
initStatements
(
output
->
size
());
...
@@ -46,20 +46,20 @@ bool lex(kj::ArrayPtr<const char> input, LexedStatements::Builder result) {
...
@@ -46,20 +46,20 @@ bool lex(kj::ArrayPtr<const char> input, LexedStatements::Builder result) {
}
}
return
true
;
return
true
;
}
else
{
}
else
{
uint32_t
best
=
parserInput
.
getBest
();
errorReporter
.
addError
(
best
,
best
,
kj
::
str
(
"Parse error."
));
return
false
;
return
false
;
}
}
}
}
bool
lex
(
kj
::
ArrayPtr
<
const
char
>
input
,
LexedTokens
::
Builder
result
)
{
bool
lex
(
kj
::
ArrayPtr
<
const
char
>
input
,
LexedTokens
::
Builder
result
,
Lexer
lexer
(
Orphanage
::
getForMessageContaining
(
result
));
ErrorReporter
&
errorReporter
)
{
Lexer
lexer
(
Orphanage
::
getForMessageContaining
(
result
),
errorReporter
);
Lexer
::
ParserInput
parserInput
(
input
.
begin
(),
input
.
end
());
auto
parser
=
p
::
sequence
(
lexer
.
getParsers
().
tokenSequence
,
p
::
endOfInput
);
kj
::
Maybe
<
kj
::
Array
<
Orphan
<
Token
>>>
parseOutput
=
lexer
.
getParsers
().
tokenSequence
(
parserInput
);
if
(
!
parserInput
.
atEnd
())
{
Lexer
::
ParserInput
parserInput
(
input
.
begin
(),
input
.
end
());
return
false
;
kj
::
Maybe
<
kj
::
Array
<
Orphan
<
Token
>>>
parseOutput
=
parser
(
parserInput
);
}
KJ_IF_MAYBE
(
output
,
parseOutput
)
{
KJ_IF_MAYBE
(
output
,
parseOutput
)
{
auto
l
=
result
.
initTokens
(
output
->
size
());
auto
l
=
result
.
initTokens
(
output
->
size
());
...
@@ -68,12 +68,12 @@ bool lex(kj::ArrayPtr<const char> input, LexedTokens::Builder result) {
...
@@ -68,12 +68,12 @@ bool lex(kj::ArrayPtr<const char> input, LexedTokens::Builder result) {
}
}
return
true
;
return
true
;
}
else
{
}
else
{
uint32_t
best
=
parserInput
.
getBest
();
errorReporter
.
addError
(
best
,
best
,
kj
::
str
(
"Parse error."
));
return
false
;
return
false
;
}
}
}
}
namespace
p
=
kj
::
parse
;
namespace
{
namespace
{
typedef
p
::
Span
<
uint32_t
>
Location
;
typedef
p
::
Span
<
uint32_t
>
Location
;
...
@@ -138,7 +138,8 @@ constexpr auto docComment = p::optional(p::sequence(
...
@@ -138,7 +138,8 @@ constexpr auto docComment = p::optional(p::sequence(
}
// namespace
}
// namespace
Lexer
::
Lexer
(
Orphanage
orphanageParam
)
:
orphanage
(
orphanageParam
)
{
Lexer
::
Lexer
(
Orphanage
orphanageParam
,
ErrorReporter
&
errorReporterParam
)
:
orphanage
(
orphanageParam
),
errorReporter
(
errorReporterParam
)
{
// Note that because passing an lvalue to a parser constructor uses it by-referencee, it's safe
// Note that because passing an lvalue to a parser constructor uses it by-referencee, it's safe
// for us to use parsers.tokenSequence even though we haven't yet constructed it.
// for us to use parsers.tokenSequence even though we haven't yet constructed it.
...
...
c++/src/capnp/compiler/lexer.h
View file @
359ea45a
...
@@ -24,15 +24,18 @@
...
@@ -24,15 +24,18 @@
#ifndef CAPNP_COMPILER_LEXER_H_
#ifndef CAPNP_COMPILER_LEXER_H_
#define CAPNP_COMPILER_LEXER_H_
#define CAPNP_COMPILER_LEXER_H_
#include
"lexer.capnp.h"
#include
<capnp/compiler/lexer.capnp.h>
#include <kj/parse/common.h>
#include <kj/parse/common.h>
#include <kj/arena.h>
#include <kj/arena.h>
#include "error-reporter.h"
namespace
capnp
{
namespace
capnp
{
namespace
compiler
{
namespace
compiler
{
bool
lex
(
kj
::
ArrayPtr
<
const
char
>
input
,
LexedStatements
::
Builder
result
);
bool
lex
(
kj
::
ArrayPtr
<
const
char
>
input
,
LexedStatements
::
Builder
result
,
bool
lex
(
kj
::
ArrayPtr
<
const
char
>
input
,
LexedTokens
::
Builder
result
);
ErrorReporter
&
errorReporter
);
bool
lex
(
kj
::
ArrayPtr
<
const
char
>
input
,
LexedTokens
::
Builder
result
,
ErrorReporter
&
errorReporter
);
// Lex the given source code, placing the results in `result`. Returns true if there
// Lex the given source code, placing the results in `result`. Returns true if there
// were no errors, false if there were. Even when errors are present, the file may have partial
// were no errors, false if there were. Even when errors are present, the file may have partial
// content which can be fed into later stages of parsing in order to find more errors.
// content which can be fed into later stages of parsing in order to find more errors.
...
@@ -46,7 +49,7 @@ class Lexer {
...
@@ -46,7 +49,7 @@ class Lexer {
// into your own parsers.
// into your own parsers.
public
:
public
:
Lexer
(
Orphanage
orphanage
);
Lexer
(
Orphanage
orphanage
,
ErrorReporter
&
errorReporter
);
// `orphanage` is used to allocate Cap'n Proto message objects in the result. `inputStart` is
// `orphanage` is used to allocate Cap'n Proto message objects in the result. `inputStart` is
// a pointer to the beginning of the input, used to compute byte offsets.
// a pointer to the beginning of the input, used to compute byte offsets.
...
@@ -62,6 +65,9 @@ public:
...
@@ -62,6 +65,9 @@ public:
explicit
ParserInput
(
ParserInput
&
parent
)
explicit
ParserInput
(
ParserInput
&
parent
)
:
IteratorInput
<
char
,
const
char
*>
(
parent
),
begin
(
parent
.
begin
)
{}
:
IteratorInput
<
char
,
const
char
*>
(
parent
),
begin
(
parent
.
begin
)
{}
inline
uint32_t
getBest
()
{
return
IteratorInput
<
char
,
const
char
*>::
getBest
()
-
begin
;
}
inline
uint32_t
getPosition
()
{
inline
uint32_t
getPosition
()
{
return
IteratorInput
<
char
,
const
char
*>::
getPosition
()
-
begin
;
return
IteratorInput
<
char
,
const
char
*>::
getPosition
()
-
begin
;
}
}
...
@@ -85,6 +91,7 @@ public:
...
@@ -85,6 +91,7 @@ public:
private
:
private
:
Orphanage
orphanage
;
Orphanage
orphanage
;
ErrorReporter
&
errorReporter
;
kj
::
Arena
arena
;
kj
::
Arena
arena
;
Parsers
parsers
;
Parsers
parsers
;
};
};
...
...
c++/src/capnp/compiler/parser.cpp
View file @
359ea45a
This diff is collapsed.
Click to expand it.
c++/src/capnp/compiler/parser.h
View file @
359ea45a
...
@@ -24,21 +24,21 @@
...
@@ -24,21 +24,21 @@
#ifndef CAPNP_COMPILER_PARSER_H_
#ifndef CAPNP_COMPILER_PARSER_H_
#define CAPNP_COMPILER_PARSER_H_
#define CAPNP_COMPILER_PARSER_H_
#include
"grammar.capnp.h"
#include
<capnp/compiler/grammar.capnp.h>
#include
"lexer.capnp.h"
#include
<capnp/compiler/lexer.capnp.h>
#include <kj/parse/common.h>
#include <kj/parse/common.h>
#include <kj/arena.h>
#include <kj/arena.h>
#include "error-reporter.h"
namespace
capnp
{
namespace
capnp
{
namespace
compiler
{
namespace
compiler
{
bool
parseFile
(
List
<
Statement
>::
Reader
statements
,
ParsedFile
::
Builder
result
);
void
parseFile
(
List
<
Statement
>::
Reader
statements
,
ParsedFile
::
Builder
result
,
ErrorReporter
&
errorReporter
);
// Parse a list of statements to build a ParsedFile.
// Parse a list of statements to build a ParsedFile.
//
class
ErrorReporter
{
// If any errors are reported, then the output is not usable. However, it may be passed on through
public
:
// later stages of compilation in order to detect additional errors.
virtual
void
addError
(
uint32_t
startByte
,
uint32_t
endByte
,
kj
::
String
message
)
=
0
;
};
class
CapnpParser
{
class
CapnpParser
{
// Advanced parser interface. This interface exposes the inner parsers so that you can embed
// Advanced parser interface. This interface exposes the inner parsers so that you can embed
...
@@ -51,13 +51,16 @@ public:
...
@@ -51,13 +51,16 @@ public:
~
CapnpParser
();
~
CapnpParser
();
KJ_DISALLOW_COPY
(
CapnpParser
);
using
ParserInput
=
kj
::
parse
::
IteratorInput
<
Token
::
Reader
,
List
<
Token
>::
Reader
::
Iterator
>
;
using
ParserInput
=
kj
::
parse
::
IteratorInput
<
Token
::
Reader
,
List
<
Token
>::
Reader
::
Iterator
>
;
struct
DeclParserResult
;
struct
DeclParserResult
;
template
<
typename
Output
>
template
<
typename
Output
>
using
Parser
=
kj
::
parse
::
ParserRef
<
ParserInput
,
Output
>
;
using
Parser
=
kj
::
parse
::
ParserRef
<
ParserInput
,
Output
>
;
using
DeclParser
=
Parser
<
DeclParserResult
>
;
using
DeclParser
=
Parser
<
DeclParserResult
>
;
Orphan
<
Declaration
>
parseStatement
(
Statement
::
Reader
statement
,
const
DeclParser
&
parser
);
kj
::
Maybe
<
Orphan
<
Declaration
>>
parseStatement
(
Statement
::
Reader
statement
,
const
DeclParser
&
parser
);
// Parse a statement using the given parser. In addition to parsing the token sequence itself,
// Parse a statement using the given parser. In addition to parsing the token sequence itself,
// this takes care of parsing the block (if any) and copying over the doc comment (if any).
// this takes care of parsing the block (if any) and copying over the doc comment (if any).
...
@@ -99,6 +102,10 @@ public:
...
@@ -99,6 +102,10 @@ public:
Parser
<
Orphan
<
DeclName
>>
declName
;
Parser
<
Orphan
<
DeclName
>>
declName
;
Parser
<
Orphan
<
TypeExpression
>>
typeExpression
;
Parser
<
Orphan
<
TypeExpression
>>
typeExpression
;
Parser
<
Orphan
<
ValueExpression
>>
valueExpression
;
Parser
<
Orphan
<
ValueExpression
>>
valueExpression
;
Parser
<
Orphan
<
ValueExpression
>>
parenthesizedValueExpression
;
Parser
<
Orphan
<
Declaration
::
AnnotationApplication
>>
annotation
;
Parser
<
Orphan
<
LocatedInteger
>>
uid
;
Parser
<
Orphan
<
LocatedInteger
>>
ordinal
;
DeclParser
usingDecl
;
DeclParser
usingDecl
;
DeclParser
constDecl
;
DeclParser
constDecl
;
...
...
c++/src/capnp/orphan.h
View file @
359ea45a
...
@@ -138,8 +138,8 @@ struct OrphanGetImpl<T, Kind::STRUCT> {
...
@@ -138,8 +138,8 @@ struct OrphanGetImpl<T, Kind::STRUCT> {
}
}
};
};
template
<
typename
T
>
template
<
typename
T
,
Kind
k
>
struct
OrphanGetImpl
<
List
<
T
>
,
Kind
::
LIST
>
{
struct
OrphanGetImpl
<
List
<
T
,
k
>
,
Kind
::
LIST
>
{
static
inline
typename
List
<
T
>::
Builder
apply
(
_
::
OrphanBuilder
&
builder
)
{
static
inline
typename
List
<
T
>::
Builder
apply
(
_
::
OrphanBuilder
&
builder
)
{
return
typename
List
<
T
>::
Builder
(
builder
.
asList
(
_
::
ElementSizeForType
<
T
>::
value
));
return
typename
List
<
T
>::
Builder
(
builder
.
asList
(
_
::
ElementSizeForType
<
T
>::
value
));
}
}
...
@@ -147,7 +147,7 @@ struct OrphanGetImpl<List<T>, Kind::LIST> {
...
@@ -147,7 +147,7 @@ struct OrphanGetImpl<List<T>, Kind::LIST> {
template
<
typename
T
>
template
<
typename
T
>
struct
OrphanGetImpl
<
List
<
T
,
Kind
::
STRUCT
>
,
Kind
::
LIST
>
{
struct
OrphanGetImpl
<
List
<
T
,
Kind
::
STRUCT
>
,
Kind
::
LIST
>
{
static
inline
typename
T
::
Builder
apply
(
_
::
OrphanBuilder
&
builder
)
{
static
inline
typename
List
<
T
>
::
Builder
apply
(
_
::
OrphanBuilder
&
builder
)
{
return
typename
List
<
T
>::
Builder
(
builder
.
asStructList
(
_
::
structSize
<
T
>
()));
return
typename
List
<
T
>::
Builder
(
builder
.
asStructList
(
_
::
structSize
<
T
>
()));
}
}
};
};
...
@@ -207,7 +207,7 @@ struct Orphanage::NewOrphanListImpl<List<T, k>> {
...
@@ -207,7 +207,7 @@ struct Orphanage::NewOrphanListImpl<List<T, k>> {
template
<
typename
T
>
template
<
typename
T
>
struct
Orphanage
::
NewOrphanListImpl
<
List
<
T
,
Kind
::
STRUCT
>>
{
struct
Orphanage
::
NewOrphanListImpl
<
List
<
T
,
Kind
::
STRUCT
>>
{
static
inline
_
::
OrphanBuilder
apply
(
_
::
BuilderArena
*
arena
,
uint
size
)
{
static
inline
_
::
OrphanBuilder
apply
(
_
::
BuilderArena
*
arena
,
uint
size
)
{
return
_
::
OrphanBuilder
::
initList
(
arena
,
size
*
ELEMENTS
,
_
::
structSize
<
T
>
());
return
_
::
OrphanBuilder
::
init
Struct
List
(
arena
,
size
*
ELEMENTS
,
_
::
structSize
<
T
>
());
}
}
};
};
...
...
c++/src/capnp/stringify-test.c++
View file @
359ea45a
...
@@ -164,6 +164,17 @@ TEST(Stringify, Unions) {
...
@@ -164,6 +164,17 @@ TEST(Stringify, Unions) {
EXPECT_EQ
(
"u3f0s64(123456789012345678)"
,
kj
::
str
(
root
.
getUnion3
()));
EXPECT_EQ
(
"u3f0s64(123456789012345678)"
,
kj
::
str
(
root
.
getUnion3
()));
}
}
TEST
(
Stringify
,
StructUnions
)
{
MallocMessageBuilder
builder
;
auto
root
=
builder
.
initRoot
<
test
::
TestStructUnion
>
();
auto
allTypes
=
root
.
getUn
().
initAllTypes
();
allTypes
.
setUInt32Field
(
12345
);
allTypes
.
setTextField
(
"foo"
);
EXPECT_EQ
(
"(un = allTypes(uInt32Field = 12345, textField =
\"
foo
\"
))"
,
kj
::
str
(
root
));
}
TEST
(
Stringify
,
MoreValues
)
{
TEST
(
Stringify
,
MoreValues
)
{
EXPECT_EQ
(
"123"
,
kj
::
str
(
DynamicValue
::
Reader
(
123
)));
EXPECT_EQ
(
"123"
,
kj
::
str
(
DynamicValue
::
Reader
(
123
)));
EXPECT_EQ
(
"1.23e47"
,
kj
::
str
(
DynamicValue
::
Reader
(
123e45
)));
EXPECT_EQ
(
"1.23e47"
,
kj
::
str
(
DynamicValue
::
Reader
(
123e45
)));
...
...
c++/src/capnp/stringify.c++
View file @
359ea45a
...
@@ -34,7 +34,7 @@ namespace {
...
@@ -34,7 +34,7 @@ namespace {
static
const
char
HEXDIGITS
[]
=
"0123456789abcdef"
;
static
const
char
HEXDIGITS
[]
=
"0123456789abcdef"
;
static
void
print
(
std
::
ostream
&
os
,
const
DynamicValue
::
Reader
&
value
,
static
void
print
(
std
::
ostream
&
os
,
const
DynamicValue
::
Reader
&
value
,
schema
::
Type
::
Body
::
Which
which
)
{
schema
::
Type
::
Body
::
Which
which
,
bool
alreadyParenthesized
=
false
)
{
// Print an arbitrary message via the dynamic API by
// Print an arbitrary message via the dynamic API by
// iterating over the schema. Look at the handling
// iterating over the schema. Look at the handling
// of STRUCT in particular.
// of STRUCT in particular.
...
@@ -127,7 +127,7 @@ static void print(std::ostream& os, const DynamicValue::Reader& value,
...
@@ -127,7 +127,7 @@ static void print(std::ostream& os, const DynamicValue::Reader& value,
break
;
break
;
}
}
case
DynamicValue
:
:
STRUCT
:
{
case
DynamicValue
:
:
STRUCT
:
{
os
<<
"("
;
if
(
!
alreadyParenthesized
)
os
<<
"("
;
auto
structValue
=
value
.
as
<
DynamicStruct
>
();
auto
structValue
=
value
.
as
<
DynamicStruct
>
();
bool
first
=
true
;
bool
first
=
true
;
for
(
auto
member
:
structValue
.
getSchema
().
getMembers
())
{
for
(
auto
member
:
structValue
.
getSchema
().
getMembers
())
{
...
@@ -151,7 +151,7 @@ static void print(std::ostream& os, const DynamicValue::Reader& value,
...
@@ -151,7 +151,7 @@ static void print(std::ostream& os, const DynamicValue::Reader& value,
}
}
}
}
}
}
os
<<
")"
;
if
(
!
alreadyParenthesized
)
os
<<
")"
;
break
;
break
;
}
}
case
DynamicValue
:
:
UNION
:
{
case
DynamicValue
:
:
UNION
:
{
...
@@ -159,7 +159,8 @@ static void print(std::ostream& os, const DynamicValue::Reader& value,
...
@@ -159,7 +159,8 @@ static void print(std::ostream& os, const DynamicValue::Reader& value,
KJ_IF_MAYBE
(
tag
,
unionValue
.
which
())
{
KJ_IF_MAYBE
(
tag
,
unionValue
.
which
())
{
os
<<
tag
->
getProto
().
getName
().
cStr
()
<<
"("
;
os
<<
tag
->
getProto
().
getName
().
cStr
()
<<
"("
;
print
(
os
,
unionValue
.
get
(),
print
(
os
,
unionValue
.
get
(),
tag
->
getProto
().
getBody
().
getFieldMember
().
getType
().
getBody
().
which
());
tag
->
getProto
().
getBody
().
getFieldMember
().
getType
().
getBody
().
which
(),
true
/* alreadyParenthesized */
);
os
<<
")"
;
os
<<
")"
;
}
else
{
}
else
{
// Unknown union member; must have come from newer
// Unknown union member; must have come from newer
...
...
c++/src/capnp/test.capnp
View file @
359ea45a
...
@@ -376,3 +376,10 @@ struct TestNewVersion {
...
@@ -376,3 +376,10 @@ struct TestNewVersion {
new1 @3 :Int64 = 987;
new1 @3 :Int64 = 987;
new2 @4 :Text = "baz";
new2 @4 :Text = "baz";
}
}
struct TestStructUnion {
un @0 union {
allTypes @1 :TestAllTypes;
object @2 :TestObject;
}
}
c++/src/kj/parse/common-test.c++
View file @
359ea45a
...
@@ -227,6 +227,77 @@ TEST(CommonParsers, ManyParserCountOnly) {
...
@@ -227,6 +227,77 @@ TEST(CommonParsers, ManyParserCountOnly) {
}
}
}
}
TEST
(
CommonParsers
,
TimesParser
)
{
StringPtr
text
=
"foobar"
;
auto
parser
=
sequence
(
exactly
(
'f'
),
times
(
any
,
4
));
{
Input
input
(
text
.
begin
(),
text
.
begin
()
+
4
);
Maybe
<
Array
<
char
>>
result
=
parser
(
input
);
EXPECT_TRUE
(
result
==
nullptr
);
EXPECT_TRUE
(
input
.
atEnd
());
}
{
Input
input
(
text
.
begin
(),
text
.
begin
()
+
5
);
Maybe
<
Array
<
char
>>
result
=
parser
(
input
);
KJ_IF_MAYBE
(
s
,
result
)
{
EXPECT_EQ
(
"ooba"
,
heapString
(
*
s
));
}
else
{
ADD_FAILURE
()
<<
"Expected string, got null."
;
}
EXPECT_TRUE
(
input
.
atEnd
());
}
{
Input
input
(
text
.
begin
(),
text
.
end
());
Maybe
<
Array
<
char
>>
result
=
parser
(
input
);
KJ_IF_MAYBE
(
s
,
result
)
{
EXPECT_EQ
(
"ooba"
,
heapString
(
*
s
));
}
else
{
ADD_FAILURE
()
<<
"Expected string, got null."
;
}
EXPECT_FALSE
(
input
.
atEnd
());
}
}
TEST
(
CommonParsers
,
TimesParserCountOnly
)
{
StringPtr
text
=
"foooob"
;
auto
parser
=
sequence
(
exactly
(
'f'
),
times
(
exactly
(
'o'
),
4
));
{
Input
input
(
text
.
begin
(),
text
.
begin
()
+
4
);
Maybe
<
Tuple
<>>
result
=
parser
(
input
);
EXPECT_TRUE
(
result
==
nullptr
);
EXPECT_TRUE
(
input
.
atEnd
());
}
{
Input
input
(
text
.
begin
(),
text
.
begin
()
+
5
);
Maybe
<
Tuple
<>>
result
=
parser
(
input
);
EXPECT_TRUE
(
result
!=
nullptr
);
EXPECT_TRUE
(
input
.
atEnd
());
}
{
Input
input
(
text
.
begin
(),
text
.
end
());
Maybe
<
Tuple
<>>
result
=
parser
(
input
);
EXPECT_TRUE
(
result
!=
nullptr
);
EXPECT_FALSE
(
input
.
atEnd
());
}
text
=
"fooob"
;
{
Input
input
(
text
.
begin
(),
text
.
end
());
Maybe
<
Tuple
<>>
result
=
parser
(
input
);
EXPECT_TRUE
(
result
==
nullptr
);
EXPECT_FALSE
(
input
.
atEnd
());
}
}
TEST
(
CommonParsers
,
ManyParserSubResult
)
{
TEST
(
CommonParsers
,
ManyParserSubResult
)
{
StringPtr
text
=
"foooob"
;
StringPtr
text
=
"foooob"
;
...
...
c++/src/kj/parse/common.h
View file @
359ea45a
...
@@ -356,7 +356,7 @@ class Many_ {
...
@@ -356,7 +356,7 @@ class Many_ {
struct
Impl
;
struct
Impl
;
public
:
public
:
explicit
constexpr
Many_
(
SubParser
&&
subParser
)
explicit
constexpr
Many_
(
SubParser
&&
subParser
)
:
subParser
(
kj
::
mv
(
subParser
))
{}
:
subParser
(
kj
::
fwd
<
SubParser
>
(
subParser
))
{}
template
<
typename
Input
>
template
<
typename
Input
>
auto
operator
()(
Input
&
input
)
const
auto
operator
()(
Input
&
input
)
const
...
@@ -395,6 +395,8 @@ struct Many_<SubParser, atLeastOne>::Impl {
...
@@ -395,6 +395,8 @@ struct Many_<SubParser, atLeastOne>::Impl {
template
<
typename
SubParser
,
bool
atLeastOne
>
template
<
typename
SubParser
,
bool
atLeastOne
>
template
<
typename
Input
>
template
<
typename
Input
>
struct
Many_
<
SubParser
,
atLeastOne
>::
Impl
<
Input
,
Tuple
<>>
{
struct
Many_
<
SubParser
,
atLeastOne
>::
Impl
<
Input
,
Tuple
<>>
{
// If the sub-parser output is Tuple<>, just return a count.
static
Maybe
<
uint
>
apply
(
const
SubParser
&
subParser
,
Input
&
input
)
{
static
Maybe
<
uint
>
apply
(
const
SubParser
&
subParser
,
Input
&
input
)
{
uint
count
=
0
;
uint
count
=
0
;
...
@@ -437,6 +439,82 @@ constexpr Many_<SubParser, true> oneOrMore(SubParser&& subParser) {
...
@@ -437,6 +439,82 @@ constexpr Many_<SubParser, true> oneOrMore(SubParser&& subParser) {
return
Many_
<
SubParser
,
true
>
(
kj
::
fwd
<
SubParser
>
(
subParser
));
return
Many_
<
SubParser
,
true
>
(
kj
::
fwd
<
SubParser
>
(
subParser
));
}
}
// -------------------------------------------------------------------
// times()
// Output = Array of output of sub-parser, or Tuple<> if sub-parser returns Tuple<>.
template
<
typename
SubParser
>
class
Times_
{
template
<
typename
Input
,
typename
Output
=
OutputType
<
SubParser
,
Input
>>
struct
Impl
;
public
:
explicit
constexpr
Times_
(
SubParser
&&
subParser
,
uint
count
)
:
subParser
(
kj
::
fwd
<
SubParser
>
(
subParser
)),
count
(
count
)
{}
template
<
typename
Input
>
auto
operator
()(
Input
&
input
)
const
->
decltype
(
Impl
<
Input
>::
apply
(
instance
<
const
SubParser
&>
(),
instance
<
uint
>
(),
input
));
private
:
SubParser
subParser
;
uint
count
;
};
template
<
typename
SubParser
>
template
<
typename
Input
,
typename
Output
>
struct
Times_
<
SubParser
>::
Impl
{
static
Maybe
<
Array
<
Output
>>
apply
(
const
SubParser
&
subParser
,
uint
count
,
Input
&
input
)
{
auto
results
=
heapArrayBuilder
<
OutputType
<
SubParser
,
Input
>>
(
count
);
while
(
results
.
size
()
<
count
)
{
if
(
input
.
atEnd
())
{
return
nullptr
;
}
else
KJ_IF_MAYBE
(
subResult
,
subParser
(
input
))
{
results
.
add
(
kj
::
mv
(
*
subResult
));
}
else
{
return
nullptr
;
}
}
return
results
.
finish
();
}
};
template
<
typename
SubParser
>
template
<
typename
Input
>
struct
Times_
<
SubParser
>::
Impl
<
Input
,
Tuple
<>>
{
// If the sub-parser output is Tuple<>, just return a count.
static
Maybe
<
Tuple
<>>
apply
(
const
SubParser
&
subParser
,
uint
count
,
Input
&
input
)
{
uint
actualCount
=
0
;
while
(
actualCount
<
count
)
{
if
(
input
.
atEnd
())
{
return
nullptr
;
}
else
KJ_IF_MAYBE
(
subResult
,
subParser
(
input
))
{
++
actualCount
;
}
else
{
return
nullptr
;
}
}
return
tuple
();
}
};
template
<
typename
SubParser
>
template
<
typename
Input
>
auto
Times_
<
SubParser
>::
operator
()(
Input
&
input
)
const
->
decltype
(
Impl
<
Input
>::
apply
(
instance
<
const
SubParser
&>
(),
instance
<
uint
>
(),
input
))
{
return
Impl
<
Input
,
OutputType
<
SubParser
,
Input
>>::
apply
(
subParser
,
count
,
input
);
}
template
<
typename
SubParser
>
constexpr
Times_
<
SubParser
>
times
(
SubParser
&&
subParser
,
uint
count
)
{
// Constructs a parser that repeats the subParser exactly `count` times.
return
Times_
<
SubParser
>
(
kj
::
fwd
<
SubParser
>
(
subParser
),
count
);
}
// -------------------------------------------------------------------
// -------------------------------------------------------------------
// optional()
// optional()
// Output = Maybe<output of sub-parser>
// Output = Maybe<output of sub-parser>
...
@@ -445,7 +523,7 @@ template <typename SubParser>
...
@@ -445,7 +523,7 @@ template <typename SubParser>
class
Optional_
{
class
Optional_
{
public
:
public
:
explicit
constexpr
Optional_
(
SubParser
&&
subParser
)
explicit
constexpr
Optional_
(
SubParser
&&
subParser
)
:
subParser
(
kj
::
mv
(
subParser
))
{}
:
subParser
(
kj
::
fwd
<
SubParser
>
(
subParser
))
{}
template
<
typename
Input
>
template
<
typename
Input
>
Maybe
<
Maybe
<
OutputType
<
SubParser
,
Input
>>>
operator
()(
Input
&
input
)
const
{
Maybe
<
Maybe
<
OutputType
<
SubParser
,
Input
>>>
operator
()(
Input
&
input
)
const
{
...
@@ -482,9 +560,8 @@ class OneOf_;
...
@@ -482,9 +560,8 @@ class OneOf_;
template
<
typename
FirstSubParser
,
typename
...
SubParsers
>
template
<
typename
FirstSubParser
,
typename
...
SubParsers
>
class
OneOf_
<
FirstSubParser
,
SubParsers
...
>
{
class
OneOf_
<
FirstSubParser
,
SubParsers
...
>
{
public
:
public
:
template
<
typename
T
,
typename
...
U
>
explicit
constexpr
OneOf_
(
FirstSubParser
&&
firstSubParser
,
SubParsers
&&
...
rest
)
explicit
constexpr
OneOf_
(
T
&&
firstSubParser
,
U
&&
...
rest
)
:
first
(
kj
::
fwd
<
FirstSubParser
>
(
firstSubParser
)),
rest
(
kj
::
fwd
<
SubParsers
>
(
rest
)...)
{}
:
first
(
kj
::
fwd
<
T
>
(
firstSubParser
)),
rest
(
kj
::
fwd
<
U
>
(
rest
)...)
{}
template
<
typename
Input
>
template
<
typename
Input
>
Maybe
<
OutputType
<
FirstSubParser
,
Input
>>
operator
()(
Input
&
input
)
const
{
Maybe
<
OutputType
<
FirstSubParser
,
Input
>>
operator
()(
Input
&
input
)
const
{
...
@@ -653,7 +730,7 @@ template <typename SubParser, typename Condition>
...
@@ -653,7 +730,7 @@ template <typename SubParser, typename Condition>
class
AcceptIf_
{
class
AcceptIf_
{
public
:
public
:
explicit
constexpr
AcceptIf_
(
SubParser
&&
subParser
,
Condition
&&
condition
)
explicit
constexpr
AcceptIf_
(
SubParser
&&
subParser
,
Condition
&&
condition
)
:
subParser
(
kj
::
mv
(
subParser
)),
condition
(
kj
::
mv
(
condition
))
{}
:
subParser
(
kj
::
fwd
<
SubParser
>
(
subParser
)),
condition
(
kj
::
fwd
<
Condition
>
(
condition
))
{}
template
<
typename
Input
>
template
<
typename
Input
>
Maybe
<
OutputType
<
SubParser
,
Input
>>
operator
()(
Input
&
input
)
const
{
Maybe
<
OutputType
<
SubParser
,
Input
>>
operator
()(
Input
&
input
)
const
{
...
@@ -692,7 +769,8 @@ constexpr AcceptIf_<SubParser, Condition> acceptIf(SubParser&& subParser, Condit
...
@@ -692,7 +769,8 @@ constexpr AcceptIf_<SubParser, Condition> acceptIf(SubParser&& subParser, Condit
template
<
typename
SubParser
>
template
<
typename
SubParser
>
class
NotLookingAt_
{
class
NotLookingAt_
{
public
:
public
:
explicit
constexpr
NotLookingAt_
(
SubParser
&&
subParser
)
:
subParser
(
kj
::
mv
(
subParser
))
{}
explicit
constexpr
NotLookingAt_
(
SubParser
&&
subParser
)
:
subParser
(
kj
::
fwd
<
SubParser
>
(
subParser
))
{}
template
<
typename
Input
>
template
<
typename
Input
>
Maybe
<
Tuple
<>>
operator
()(
Input
&
input
)
const
{
Maybe
<
Tuple
<>>
operator
()(
Input
&
input
)
const
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment